| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- import { View, Text, ScrollView, StyleSheet, Image, ActivityIndicator } from 'react-native';
- import React, { useEffect, useState } from 'react';
- import { SafeAreaView } from 'react-native-safe-area-context';
- import NormalButton from '../global/normal_button';
- import ExpectedFeeBox from '../global/expectedFeeBox';
- import OtherInformationBox from '../global/otherInformationBox';
- import { BatteryLogoSvg, TimeClockLogoSvg, WarningTriangleLogoSvg } from '../global/SVG';
- import { router } from 'expo-router';
- const IdlingGreyBox = () => {
- 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>
- </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>
- </View>
- <View className="w-[60%]">
- <Text style={styles.warningBoldText}>01:55</Text>
- </View>
- </View>
- <View className="flex-row items-center ">
- <View>
- <Text className="text-sm text-white">請於下方確認完成充電以免進入罰款時間</Text>
- </View>
- </View>
- </View>
- </View>
- );
- };
- const ChargingPenaltyPageComponent = ({ data }) => {
- const [isIdling, setIsIdling] = React.useState<boolean>(false);
- const reservationData = Array.isArray(data) ? data[0] : data;
- const [loading, setLoading] = useState(false);
- //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時
- const [timeSince, setTimeSince] = useState<string>('');
- useEffect(() => {
- const updateTimeSince = () => {
- if (reservationData && reservationData.actual_start_time) {
- setTimeSince(timeSinceBooking(reservationData.actual_start_time) || '計算中...');
- } else {
- setTimeSince('計算中...');
- }
- };
- updateTimeSince();
- // Update every minute
- const intervalId = setInterval(updateTimeSince, 60000);
- // Cleanup interval on component unmount
- return () => clearInterval(intervalId);
- }, [reservationData]);
- function timeSinceBooking(timeString) {
- if (timeString) {
- const startTime = new Date(timeString);
- const now = new Date();
- const diffInMilliseconds = now - startTime;
- const diffInMinutes = Math.floor(diffInMilliseconds / (1000 * 60));
- if (diffInMinutes < 1) {
- return '< 1 m';
- } else {
- return `${diffInMinutes} m${diffInMinutes !== 1 ? 's' : ''}`;
- }
- }
- }
- //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時 //用來計充電歷時
- const PenaltyRedBox = () => {
- const penalty_time = reservationData.actual_end_time;
- return (
- <>
- <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>
- </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>
- </View>
- <View className="w-[60%]">
- <Text style={styles.warningBoldText}>{penaltyTime}</Text>
- </View>
- </View>
- <View className="flex-1 flex-row items-center pb-2">
- <View className="w-[40%]">
- <Text style={styles.warningLightText}>累積:</Text>
- </View>
- <View className="w-[60%]">
- <Text style={styles.warningBoldText}>01:55</Text>
- </View>
- </View>
- <View className="flex-1 flex-row items-center pb-2">
- <View>
- <Text style={styles.warningLightText}>請於下方確認完成充電以解鎖</Text>
- </View>
- </View>
- </View>
- </>
- );
- };
- //用來計算penalty
- const [penaltyTime, setPenaltyTime] = useState<string>('');
- useEffect(() => {
- const updatePenaltyTime = () => {
- if (reservationData.actual_end_time) {
- setPenaltyTime(calculatePenaltyTime(reservationData.actual_end_time) || '計算中...');
- } else {
- setPenaltyTime('尚未結束充電');
- }
- };
- updatePenaltyTime();
- // Update every 30 seconds
- const intervalId = setInterval(updatePenaltyTime, 30000);
- // Cleanup interval on component unmount
- return () => clearInterval(intervalId);
- }, [reservationData.actual_end_time]);
- function calculatePenaltyTime(endTimeString: any) {
- if (endTimeString) {
- const endTime = new Date(endTimeString);
- const graceEndTime = new Date(endTime.getTime() + 15 * 60000); // Add 15 minutes
- const now = new Date();
- const diffInMilliseconds = now - graceEndTime;
- const diffInMinutes = Math.floor(diffInMilliseconds / (1000 * 60));
- if (diffInMinutes < 0) {
- return '0 m'; // No penalty yet
- } else if (diffInMinutes === 0) {
- return '< 1 m';
- } else {
- return `${diffInMinutes} m ${diffInMinutes !== 1 ? 's' : ''}`;
- }
- }
- }
- if (loading) {
- return (
- <SafeAreaView style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
- <ActivityIndicator size="large" />
- <Text>Loading...</Text>
- </SafeAreaView>
- );
- }
- return (
- <SafeAreaView className="flex-1 bg-white" edges={['top', 'left', 'right']}>
- <ScrollView className="flex-1" showsVerticalScrollIndicator={false}>
- <View className="mx-[5%]">
- <View className="my-4">
- <Text className="text-xl" style={styles.greenColor}>
- 已完成充電
- </Text>
- <Text className="text-2xl">
- {reservationData.car.car_brand.name} {reservationData.car.car_type.name}
- </Text>
- </View>
- <View className="flex-row items-center ">
- <View className="w-[50%] items-center justify-center">
- <Image
- source={require('../../assets/car.png')}
- resizeMode="contain"
- style={{ height: 127, width: 220 }}
- />
- </View>
- <View className="w-[50%] flex-column items-center ">
- <View className="flex-row items-center space-x-4">
- <View>
- <BatteryLogoSvg />
- </View>
- <View className="flex-column">
- <Text className="text-sm" style={styles.grayColor}>
- 已充電
- </Text>
- <Text style={styles.greenColor} className="text-3xl font-light">
- {reservationData.Soc}%
- </Text>
- </View>
- </View>
- <View className="flex-row items-center space-x-4">
- <View>
- <TimeClockLogoSvg />
- </View>
- <View className="flex-column">
- <Text className="text-sm" style={styles.grayColor}>
- 充電歷時
- </Text>
- <View className="flex-row items-end">
- <Text style={styles.greenColor} className="text-2xl font-light">
- {timeSince}
- </Text>
- </View>
- </View>
- </View>
- </View>
- </View>
- {isIdling ? (
- <View className=" flex-column py-3">
- <IdlingGreyBox />
- </View>
- ) : (
- <View className="flex-column py-3">
- <PenaltyRedBox />
- </View>
- )}
- <View>
- <NormalButton
- onPress={() => {
- router.push('chargingPage');
- }}
- title={
- <Text className="text-xl text-white " style={{ fontWeight: 900 }}>
- 完成充電
- </Text>
- }
- />
- </View>
- <ExpectedFeeBox extendedStyle={{ marginTop: 12, padding: 12 }} price={reservationData.total_fee} />
- <OtherInformationBox
- extendedStyle={{ marginTop: 12, padding: 12 }}
- actual_start_time={reservationData.actual_start_time}
- />
- <View className="mt-2">
- <NormalButton
- title={<Text className="text-white text-xl font-semibold">觀看閒置狀態頁面</Text>}
- onPress={() => setIsIdling((prevState) => !prevState)}
- />
- </View>
- </View>
- </ScrollView>
- </SafeAreaView>
- );
- };
- export default ChargingPenaltyPageComponent;
- const styles = StyleSheet.create({
- grayColor: {
- color: '#888888'
- },
- greenColor: {
- color: '#02677D'
- },
- text: {
- fontWeight: '300',
- color: '#000000'
- },
- warningLightText: {
- color: 'white',
- fontSize: 15,
- fontWeight: '400'
- },
- warningBoldText: {
- color: 'white',
- fontSize: 20,
- fontWeight: '700'
- }
- });
|