|
|
@@ -0,0 +1,147 @@
|
|
|
+//the size of the TabView will follow its parent-container's size.
|
|
|
+
|
|
|
+import * as React from 'react';
|
|
|
+import {
|
|
|
+ View,
|
|
|
+ Text,
|
|
|
+ useWindowDimensions,
|
|
|
+ StyleSheet,
|
|
|
+ Image,
|
|
|
+ ImageSourcePropType
|
|
|
+} from 'react-native';
|
|
|
+import { TabView, SceneMap, TabBar } from 'react-native-tab-view';
|
|
|
+import { FlashList } from '@shopify/flash-list';
|
|
|
+
|
|
|
+export interface TabItem {
|
|
|
+ imgURL: ImageSourcePropType;
|
|
|
+ date: string;
|
|
|
+ time: string;
|
|
|
+ chargeStationName: string;
|
|
|
+ chargeStationAddress: string;
|
|
|
+ distance: string;
|
|
|
+}
|
|
|
+
|
|
|
+interface TabViewComponentProps {
|
|
|
+ titles: string[];
|
|
|
+ tabItems: TabItem[];
|
|
|
+}
|
|
|
+const TabViewComponent: React.FC<TabViewComponentProps> = ({
|
|
|
+ titles,
|
|
|
+ tabItems
|
|
|
+}) => {
|
|
|
+ const layout = useWindowDimensions();
|
|
|
+
|
|
|
+ //tab 1
|
|
|
+ const FirstRoute = () => (
|
|
|
+ <View style={{ flex: 1, backgroundColor: 'white' }}>
|
|
|
+ <FlashList
|
|
|
+ data={tabItems}
|
|
|
+ renderItem={({ item }) => {
|
|
|
+ return (
|
|
|
+ <View style={styles.container}>
|
|
|
+ <Image style={styles.image} source={item.imgURL} />
|
|
|
+ <View style={styles.textContainer}>
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontWeight: 700,
|
|
|
+ color: '#02677D',
|
|
|
+ fontSize: 20
|
|
|
+ }}
|
|
|
+ >{`${item.date} - ${item.time}`}</Text>
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontWeight: 400,
|
|
|
+ fontSize: 16,
|
|
|
+ color: '#222222'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {item.chargeStationName}
|
|
|
+ </Text>
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontWeight: 400,
|
|
|
+ fontSize: 16,
|
|
|
+ color: '#888888'
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {item.chargeStationAddress}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ fontWeight: 400,
|
|
|
+ fontSize: 16,
|
|
|
+ color: '#888888',
|
|
|
+ marginTop: 20,
|
|
|
+ marginLeft: 10
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {item.distance}
|
|
|
+ </Text>
|
|
|
+ </View>
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ estimatedItemSize={10}
|
|
|
+ />
|
|
|
+ </View>
|
|
|
+ );
|
|
|
+
|
|
|
+ //tab 2
|
|
|
+ const SecondRoute = () => (
|
|
|
+ <View style={{ flex: 1, backgroundColor: 'white' }} />
|
|
|
+ );
|
|
|
+
|
|
|
+ const renderScene = SceneMap({
|
|
|
+ firstRoute: FirstRoute,
|
|
|
+ secondRoute: SecondRoute
|
|
|
+ });
|
|
|
+ const [routes] = React.useState([
|
|
|
+ { key: 'firstRoute', title: titles[0] },
|
|
|
+ { key: 'secondRoute', title: titles[1] }
|
|
|
+ ]);
|
|
|
+ const [index, setIndex] = React.useState(0);
|
|
|
+
|
|
|
+ const renderTabBar = (props: any) => (
|
|
|
+ <TabBar
|
|
|
+ {...props}
|
|
|
+ renderLabel={({ route, focused }) => (
|
|
|
+ <Text
|
|
|
+ style={{
|
|
|
+ color: focused ? '#025c72' : '#888888',
|
|
|
+ fontWeight: focused ? '900' : 'thin',
|
|
|
+ fontSize: 20
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {route.title}
|
|
|
+ </Text>
|
|
|
+ )}
|
|
|
+ indicatorStyle={{
|
|
|
+ backgroundColor: '#025c72'
|
|
|
+ }}
|
|
|
+ style={{
|
|
|
+ backgroundColor: 'white',
|
|
|
+ borderTopWidth: 4,
|
|
|
+ borderColor: '#DBE4E8',
|
|
|
+ elevation: 0,
|
|
|
+ marginHorizontal: 15,
|
|
|
+ borderBottomWidth: 0.5
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ return (
|
|
|
+ <TabView
|
|
|
+ navigationState={{ index, routes }}
|
|
|
+ renderScene={renderScene}
|
|
|
+ onIndexChange={setIndex}
|
|
|
+ initialLayout={{ width: layout.width }}
|
|
|
+ renderTabBar={renderTabBar}
|
|
|
+ />
|
|
|
+ );
|
|
|
+};
|
|
|
+export default TabViewComponent;
|
|
|
+
|
|
|
+const styles = StyleSheet.create({
|
|
|
+ container: { flexDirection: 'row' },
|
|
|
+ image: { width: 100, height: 100, margin: 15, borderRadius: 10 },
|
|
|
+ textContainer: { flexDirection: 'column', gap: 8, marginTop: 20 }
|
|
|
+});
|