Explorar el Código

created tab view component at global/tabView.tsx

Ian Fung hace 1 año
padre
commit
ad59eb6ccd

BIN
assets/dummyStationPicture.png


BIN
assets/dummyStationPicture2.png


+ 147 - 0
component/global/tabView.tsx

@@ -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 }
+});

+ 24 - 0
package-lock.json

@@ -25,9 +25,11 @@
         "react-native-keyboard-aware-scroll-view": "^0.9.5",
         "react-native-maps": "1.14.0",
         "react-native-modern-datepicker": "^1.0.0-beta.91",
+        "react-native-pager-view": "6.3.0",
         "react-native-safe-area-context": "4.10.1",
         "react-native-screens": "3.31.1",
         "react-native-svg": "^15.3.0",
+        "react-native-tab-view": "^3.5.2",
         "zustand": "^4.5.2"
       },
       "devDependencies": {
@@ -12812,6 +12814,15 @@
         "react-native": ">=0.59"
       }
     },
+    "node_modules/react-native-pager-view": {
+      "version": "6.3.0",
+      "resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.3.0.tgz",
+      "integrity": "sha512-ufJOoVa9pFL1J/yb4hpsCqp8n1qTlcF5VvwqvCacHX//D7hSeRscsiIXg1u1pXNWwllvACb+mqxec/3Uj2mxrA==",
+      "peerDependencies": {
+        "react": "*",
+        "react-native": "*"
+      }
+    },
     "node_modules/react-native-safe-area-context": {
       "version": "4.10.1",
       "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.10.1.tgz",
@@ -12847,6 +12858,19 @@
         "react-native": "*"
       }
     },
+    "node_modules/react-native-tab-view": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-3.5.2.tgz",
+      "integrity": "sha512-nE5WqjbeEPsWQx4mtz81QGVvgHRhujTNIIZiMCx3Bj6CBFDafbk7XZp9ocmtzXUQaZ4bhtVS43R4FIiR4LboJw==",
+      "dependencies": {
+        "use-latest-callback": "^0.1.5"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-native": "*",
+        "react-native-pager-view": "*"
+      }
+    },
     "node_modules/react-native/node_modules/ansi-styles": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",

+ 3 - 1
package.json

@@ -9,6 +9,7 @@
     "web": "expo start --web"
   },
   "dependencies": {
+    "@shopify/flash-list": "1.6.4",
     "@types/react-native-datepicker": "^1.7.6",
     "axios": "^1.6.7",
     "dotenv": "^16.4.5",
@@ -28,8 +29,9 @@
     "react-native-safe-area-context": "4.10.1",
     "react-native-screens": "3.31.1",
     "react-native-svg": "^15.3.0",
+    "react-native-tab-view": "^3.5.2",
     "zustand": "^4.5.2",
-    "@shopify/flash-list": "1.6.4"
+    "react-native-pager-view": "6.3.0"
   },
   "devDependencies": {
     "@babel/core": "^7.20.0",