//the size of the TabView will follow its parent-container's size. import * as React from 'react'; import { View, Text, useWindowDimensions, StyleSheet, ScrollView, ActivityIndicator, Pressable } from 'react-native'; import { TabView, TabBar } from 'react-native-tab-view'; import { formatToChineseDateTime } from '../../util/lib'; import { useCallback, useEffect, useState } from 'react'; import { notificationStorage } from '../notificationStorage'; import { router, useFocusEffect } from 'expo-router'; export interface TabItem { title: string; description: string; date: string; } interface TabViewComponentProps { titles: string[]; reservationAfter2025: any; passingThisPromotionToBell: any; } const NotificationRow = ({ promotionObj, index, viewedNotifications }: { promotionObj: any; index: number; viewedNotifications: any; }) => { const isViewed = viewedNotifications.some( (notification: any) => notification.id === promotionObj.id && notification.type === 'promotion' ); const handlePress = async () => { // Mark promotion as viewed await notificationStorage.markAsViewed(promotionObj.id, 'promotion'); router.push({ pathname: '/notificationDetailPage', params: { promotion: JSON.stringify(promotionObj) } }); }; return ( {promotionObj.title} {formatToChineseDateTime(promotionObj.createdAt)} {promotionObj.text} ); }; const ReservationRow = ({ reservationObj, index, viewedNotifications }: { reservationObj: any; index: number; viewedNotifications: any; }) => { const isViewed = viewedNotifications.some( (notification: any) => notification.id === reservationObj.id && notification.type === 'reservation' ); const handlePress = async () => { await notificationStorage.markAsViewed(reservationObj.id, 'reservation'); if (reservationObj.status.id === '7') { router.push({ pathname: '/chargingPage' }); } else { router.push({ pathname: '/chargingDetailPage', params: { promotion: JSON.stringify(reservationObj) } }); } }; const title = reservationObj.status.id === '8' || reservationObj.status.id === '13' ? '充電完成' : reservationObj.status.id === '7' ? '充電進行中' : ''; const text = reservationObj.status.id === '8' || reservationObj.status.id === '13' ? '親愛的用戶,您的愛車已充滿電完成!請盡快駛離充電站,以便其他車輛使用。感謝您的配合!' : reservationObj.status.id === '7' ? `您的車輛正在充電中,當時充電百分比為${reservationObj.Soc}%。詳情請按我進入充電頁面查看。` : ''; return ( {title} {formatToChineseDateTime(reservationObj.createdAt)} {text} ); }; const FirstRoute = ({ loading, reservationAfter2025 }: { loading: boolean; reservationAfter2025: any }) => { const [viewedNotifications, setViewedNotifications] = useState([]); useFocusEffect( useCallback(() => { const getViewedNotifications = async () => { const notifications = await notificationStorage.getViewedNotifications(); setViewedNotifications(notifications); }; getViewedNotifications(); }, []) ); return ( {loading ? ( ) : ( {reservationAfter2025.length === 0 ? ( 暫時沒有充電資訊。 ) : ( reservationAfter2025 .sort( (a: any, b: any) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ) .filter( (reservationObj: any) => reservationObj.status.id === '7' || reservationObj.status.id === '8' || reservationObj.status.id === '13' ) .slice(0, 30) .map((reservationObj: any, index: any) => ( )) )} )} ); }; const SecondRoute = ({ promotions, loading }: { promotions: TabItem[]; loading: boolean }) => { const [viewedNotifications, setViewedNotifications] = useState([]); useFocusEffect( useCallback(() => { const getViewedNotifications = async () => { const notifications = await notificationStorage.getViewedNotifications(); setViewedNotifications(notifications); }; getViewedNotifications(); }, []) ); return ( {loading ? ( ) : ( {promotions.length === 0 ? ( 暫時沒有通知消息。 ) : ( promotions .sort( (a: any, b: any) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() ) .slice(0, 30) .map((promotionObj: any, index: any) => ( )) )} )} ); }; const NotificationTabView: React.FC = ({ titles, reservationAfter2025, passingThisPromotionToBell }) => { const layout = useWindowDimensions(); const [loading, setLoading] = useState(false); //fetch promotion data // useEffect(() => { // const fetchMainPromotion = async () => { // try { // setLoading(true); // const response = await chargeStationService.getAdvertise(); // if (response) { // setMainPromotion(response); // } // } catch (error) { // console.log('Error fetching promotion:', error); // } finally { // setLoading(false); // } // }; // fetchMainPromotion(); // }, []); // const handleCouponClick = async (clickedCoupon: string) => { // Alert.alert( // '立即使用優惠券', // Title // '按確認打開相機,掃描充電站上的二維碼以使用優惠券', // Message // [ // { // text: '取消', // style: 'cancel' // }, // { // text: '確認', // onPress: () => router.push('scanQrPage') // } // ] // ); // }; const renderScene = useCallback( ({ route }: { route: any }) => { switch (route.key) { case 'firstRoute': return ; case 'secondRoute': return ; default: return null; } }, [loading] ); const [routes] = React.useState([ { key: 'firstRoute', title: titles[0] }, { key: 'secondRoute', title: titles[1] } ]); const [index, setIndex] = React.useState(0); const renderTabBar = (props: any) => ( ( {route.title} )} indicatorStyle={{ backgroundColor: '#025c72' }} style={{ backgroundColor: 'white', borderColor: '#DBE4E8', elevation: 0, marginHorizontal: 15, borderBottomWidth: 0.5 }} /> ); return ( ); }; export default NotificationTabView; const styles = StyleSheet.create({ container: { flexDirection: 'row' }, image: { width: 100, height: 100, margin: 15, borderRadius: 10 }, textContainer: { flexDirection: 'column', gap: 8, marginTop: 20 }, floatingButton: { elevation: 5, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.25, shadowRadius: 3.84 } });