Ian Fung 1 年之前
父節點
當前提交
c8a3ef438e

+ 93 - 26
app/(auth)/(tabs)/(home)/scanQrPage.tsx

@@ -106,14 +106,17 @@ const ScanQrPage = () => {
                               backgroundColor: 'rgba(0,0,0,0.7)'
                           }
                         : {
-                              marginVertical: '5%',
-                              paddingBottom: 12,
-                              backgroundColor: 'rgba(0,0,0,0.7)'
+                              //   marginVertical: '5%',
+                              //   paddingBottom: 12,
+
+                              flex: 1,
+                              alignItems: 'center',
+                              justifyContent: 'center'
                           })
                 }}
             >
-                <View className="mx-[5%] items-center">
-                    <View className="flex-row items-center justify-between  w-full">
+                <View className=" justify-center items-center flex-1">
+                    {/* <View className="flex-row items-center justify-between  w-full">
                         <View className="pt-2">
                             <Pressable
                                 className=""
@@ -132,32 +135,96 @@ const ScanQrPage = () => {
                             選擇充電車輛
                         </Text>
                         <Text className="text-xl text-white pt-2"></Text>
-                    </View>
+                    </View> */}
 
-                    <ScrollView
-                        horizontal={true}
-                        showsHorizontalScrollIndicator={false}
-                        contentContainerStyle={{
-                            alignItems: 'center',
-                            flexDirection: 'row',
-                            marginVertical: 8
+                    <View
+                        style={{
+                            ...(isLargeScreen
+                                ? {}
+                                : {
+                                      backgroundColor: 'rgba(0,0,0,0.7)',
+                               
+                                  })
                         }}
-                        className="space-x-2"
                     >
-                        {dummyDataChooseCarForCharging.map((car, index) => (
-                            <ChooseCarForChargingRow
-                                onPress={() =>
-                                    router.push(
-                                        '/(auth)/(tabs)/(charging)/chargingPage'
+                        <View className="w-full">
+                            <View className="flex-row items-center justify-between mx-[5%] ">
+                                <Pressable
+                                    className="pt-4 "
+                                    onPress={() => {
+                                        if (router.canGoBack()) {
+                                            router.back();
+                                        } else {
+                                            router.replace('mainPage');
+                                        }
+                                    }}
+                                >
+                                    <CrossLogoWhiteSvg />
+                                </Pressable>
+
+                                <Text className="text-base text-white pt-2">
+                                    選擇充電車輛
+                                </Text>
+                                <Text className="text-xl text-white pt-2"></Text>
+                            </View>
+
+                            <ScrollView
+                                horizontal={true}
+                                showsHorizontalScrollIndicator={false}
+                                contentContainerStyle={{
+                                    alignItems: 'center',
+                                    flexDirection: 'row',
+                                    marginVertical: 12
+                                }}
+                                className="space-x-2 mx-[5%]"
+                            >
+                                {dummyDataChooseCarForCharging.map(
+                                    (car, index) => (
+                                        <ChooseCarForChargingRow
+                                            onPress={() =>
+                                                router.push(
+                                                    '/(auth)/(tabs)/(charging)/chargingPage'
+                                                )
+                                            }
+                                            imageUrl={car.imageUrl}
+                                            key={`${car.VehicleName}+${index}`}
+                                            VehicleName={car.VehicleName}
+                                            isDefault={car.isDefault}
+                                        />
                                     )
+                                )}
+                            </ScrollView>
+                        </View>
+
+                        {/* <ScrollView
+                            horizontal={true}
+                            showsHorizontalScrollIndicator={false}
+                            contentContainerStyle={
+                                {
+                                    alignItems: 'center',
+                                    flexDirection: 'row',
+                                    marginVertical: 8
                                 }
-                                imageUrl={car.imageUrl}
-                                key={`${car.VehicleName}+${index}`}
-                                VehicleName={car.VehicleName}
-                                isDefault={car.isDefault}
-                            />
-                        ))}
-                    </ScrollView>
+                            }
+                            className="space-x-2"
+                        >
+                            {dummyDataChooseCarForCharging.map((car, index) => (
+                                <ChooseCarForChargingRow
+                                    onPress={() =>
+                                        router.push(
+                                            '/(auth)/(tabs)/(charging)/chargingPage'
+                                        )
+                                    }
+                                    imageUrl={car.imageUrl}
+                                    key={`${car.VehicleName}+${index}`}
+                                    VehicleName={car.VehicleName}
+                                    isDefault={car.isDefault}
+                                />
+                            ))}
+                        </ScrollView> */}
+
+                        {/* <Text className='text-2xl'>Hello</Text> */}
+                    </View>
                 </View>
             </View>
         );

+ 80 - 32
component/bookingMenuPage/makingBookingPageComponent.tsx

@@ -5,7 +5,8 @@ import {
     Pressable,
     StyleSheet,
     Image,
-    Dimensions
+    Dimensions,
+    ActivityIndicator
 } from 'react-native';
 import { SafeAreaView } from 'react-native-safe-area-context';
 import { router } from 'expo-router';
@@ -17,8 +18,9 @@ import {
 } from '../global/SVG';
 import { ChargingStationTabView } from '../global/chargingStationTabView';
 import ChooseCarForChargingRow from '../global/chooseCarForChargingRow';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
 import DropdownSelect from '../global/dropdown_select';
+import { chargeStationService } from '../../service/chargeStationService';
 
 const dummyDataChooseCarForCharging = [
     {
@@ -69,13 +71,48 @@ const AccordionItem: React.FC<AccordionItemProps> = ({
 const MakingBookingPageComponent = () => {
     const [openDrawer, setOpenDrawer] = useState<number | null>(0);
     const [selectedTime, setSelectedTime] = useState<string>('');
+    const [availableTimeSlots, setAvailableTimeSlots] = useState<string[]>([]);
     const [selectedDrawer, setSelectedDrawer] = useState<number>(0);
+    const [isLoading, setIsLoading] = useState(true);
     const [selectedDate, setSelectedDate] = useState<string>('');
     const toggleDrawer = (index: number) => {
         setOpenDrawer(openDrawer === index ? null : index);
         setSelectedDrawer(index);
     };
 
+    const [availableDate, setAvailableDate] = useState<string[]>([]);
+    useEffect(() => {
+        const fetchingAvailableDates = async () => {
+            const fetchedDates = await chargeStationService.fetchAvailableDates(
+                '2405311022116801000'
+            );
+            setAvailableDate(fetchedDates);
+        };
+        fetchingAvailableDates();
+    }, []);
+
+    useEffect(() => {
+        const fetchingAvailableTimeSlots = async () => {
+            setIsLoading(true);
+            try {
+                const fetchedTimeSlots =
+                    await chargeStationService.fetchAvailableTimeSlots(
+                        '2405311022116801000',
+                        selectedDate
+                    );
+                setAvailableTimeSlots(fetchedTimeSlots);
+                console.log(`I AM TIMESLOT ${fetchedTimeSlots}`);
+            } catch (error) {
+                console.error('Error fetching time slots:', error);
+            } finally {
+                setIsLoading(false);
+            }
+        };
+        if (selectedDate) {
+            fetchingAvailableTimeSlots();
+        }
+    }, [selectedDate]);
+
     const timeData = [
         '14:00',
         '14:15',
@@ -131,7 +168,10 @@ const MakingBookingPageComponent = () => {
             }}
             edges={['right', 'top', 'left']}
         >
-            <ScrollView className="flex-1 bg-white ">
+            <ScrollView
+                className="flex-1 bg-white"
+                showsVerticalScrollIndicator={false}
+            >
                 <View className="pb-4 ">
                     <View className="ml-[5%] pt-8">
                         <Pressable
@@ -332,6 +372,7 @@ const MakingBookingPageComponent = () => {
                                     </Text>
                                 </Pressable>
                             </View>
+
                             {chargingBasedOnWatt === true && (
                                 <View className="flex-row w-full justify-between mb-3">
                                     {['30分鐘', '45分鐘', '60分鐘', '其他'].map(
@@ -404,15 +445,15 @@ const MakingBookingPageComponent = () => {
                             }}
                             isSelected={selectedDrawer === 2}
                         >
-                            <View className="flex-row w-full justify-between mb-3 flex-wrap my-2 ">
-                                {dateData.map((date) => (
+                            <View className="flex-row w-full flex-wrap mb-1 ">
+                                {availableDate.map((date) => (
                                     <Pressable
                                         key={date}
                                         className={`${
                                             selectedDate === date
                                                 ? 'bg-[#34667c] '
                                                 : 'bg-white'
-                                        } border border-[#34667c]  rounded-lg w-[22%] items-center mb-2`}
+                                        } border border-[#34667c]  rounded-lg w-[22%] items-center mt-1 mr-1 mb-1`}
                                         onPress={() => {
                                             setSelectedDate(date);
                                         }}
@@ -435,33 +476,40 @@ const MakingBookingPageComponent = () => {
                                     <Text className="text-lg pr-2 ">
                                         選擇時間
                                     </Text>
-                                    <View className="flex-row w-full justify-between mb-3 flex-wrap my-2 ">
-                                        {timeData.map((time) => (
-                                            <Pressable
-                                                key={time}
-                                                className={`${
-                                                    selectedTime === time
-                                                        ? 'bg-[#34667c] '
-                                                        : 'bg-white'
-                                                } border border-[#34667c]  rounded-lg w-[22%] items-center mb-2`}
-                                                onPress={() => {
-                                                    setSelectedTime(time);
-                                                    setOpenDrawer(3);
-                                                    setSelectedDrawer(3);
-                                                }}
-                                            >
-                                                <Text
-                                                    className={`text-base p-2  ${
+                                    {isLoading ? (
+                                        <View className="flex-1 mb-2">
+                                            <ActivityIndicator />
+                                        </View>
+                                    ) : (
+                                        <View className="flex-row w-full justify-between mb-3 flex-wrap my-2 ">
+                                            {availableTimeSlots.map((time) => (
+                                                <Pressable
+                                                    key={time}
+                                                    className={`${
                                                         selectedTime === time
-                                                            ? 'text-white'
-                                                            : 'text-[#34667c]'
-                                                    } `}
+                                                            ? 'bg-[#34667c] '
+                                                            : 'bg-white'
+                                                    } border border-[#34667c]  rounded-lg w-[22%] items-center mb-2`}
+                                                    onPress={() => {
+                                                        setSelectedTime(time);
+                                                        setOpenDrawer(3);
+                                                        setSelectedDrawer(3);
+                                                    }}
                                                 >
-                                                    {time}
-                                                </Text>
-                                            </Pressable>
-                                        ))}
-                                    </View>
+                                                    <Text
+                                                        className={`text-base p-2  ${
+                                                            selectedTime ===
+                                                            time
+                                                                ? 'text-white'
+                                                                : 'text-[#34667c]'
+                                                        } `}
+                                                    >
+                                                        {time}
+                                                    </Text>
+                                                </Pressable>
+                                            ))}
+                                        </View>
+                                    )}
                                 </>
                             )}
                         </AccordionItem>
@@ -502,7 +550,7 @@ const MakingBookingPageComponent = () => {
                                     resizeMode="contain"
                                     source={require('../../assets/ChargeStationLayout.png')}
                                 />
-                            </View >
+                            </View>
                         </AccordionItem>
                     </View>
                 </View>

+ 1 - 1
component/chargingPage/paymentSummaryPageComponent.tsx

@@ -28,7 +28,7 @@ const PaymentSummaryPageComponent = () => {
                         <Pressable onPress={() => console.log('優惠券')}>
                             <Text className="text-lg pb-4">優惠券</Text>
                             <View className="bg-[#e9f2f7] rounded-xl h-[9vh] items-center flex-row pl-6 justify-between">
-                                <View className="flex-row ">
+                                <View className="flex-row items-center ">
                                     <TickLogoSvg />
                                     <Text className="color-[#34667c] px-4 text-base">
                                         $20 迎新優惠券

+ 1 - 1
component/global/chooseCarForChargingRow.tsx

@@ -11,7 +11,7 @@ import { StarSvg } from './SVG';
 import { router } from 'expo-router';
 
 const { width, height } = Dimensions.get('window');
-const imageHeight = height < 700 ? 100 : 140;
+const imageHeight = height < 700 ? 100 : 130;
 const imageWidth = width < 400 ? 120 : 146;
 
 const carHeight = height < 700 ? 48 : 72;

+ 3 - 3
component/homePage/homePage.tsx

@@ -12,12 +12,12 @@ const HomePage: React.FC<HomePageProps> = () => {
     const { user } = useContext(AuthContext);
 
     return (
-        <SafeAreaView edges={['left', 'right']} className="flex-1 bg-white">
+        <SafeAreaView edges={['top','left', 'right']} className="flex-1 bg-white">
             <ScrollView
                 showsVerticalScrollIndicator={false}
-                className="flex-1 mx-[5%] mt-8 "
+                className="flex-1 mx-[5%] "
             >
-                <View className="">
+                <View className="pt-8">
                     <View className="flex-row items-center pb-4">
                         <HomeIconSvg />
                         <View className="pl-2 flex-1 flex-column ">

+ 259 - 232
component/reservationLocationPage/reservationLocationPageComponent.tsx

@@ -7,7 +7,8 @@ import {
     StyleSheet,
     Image,
     ImageSourcePropType,
-    Pressable
+    Pressable,
+    ActivityIndicator
 } from 'react-native';
 import { TabView, SceneMap, TabBar } from 'react-native-tab-view';
 import { FlashList } from '@shopify/flash-list';
@@ -15,6 +16,8 @@ import { SafeAreaView } from 'react-native-safe-area-context';
 
 import { router } from 'expo-router';
 import { CheckMarkLogoSvg, CrossLogoSvg } from '../global/SVG';
+import { useEffect, useState } from 'react';
+import { chargeStationService } from '../../service/chargeStationService';
 
 interface TabItem {
     imgURL: ImageSourcePropType;
@@ -23,6 +26,7 @@ interface TabItem {
     chargeStationName: string;
     chargeStationAddress: string;
     distance: string;
+    stationID: string;
 }
 
 interface TabViewComponentProps {
@@ -30,264 +34,287 @@ interface TabViewComponentProps {
     tabItems: TabItem[];
 }
 
-const dummyTabItems: TabItem[] = [
-    {
-        imgURL: require('../../assets/dummyStationPicture.png'),
-        date: '今天',
-        time: '16:30',
-        chargeStationName: '上環街市充電站',
-        chargeStationAddress: '香港上環皇后大道中345號',
-        distance: '400米'
-    },
-    {
-        imgURL: require('../../assets/dummyStationPicture2.png'),
-        date: '3月15',
-        time: '17:45',
-        chargeStationName: '中環IFC充電站',
-        chargeStationAddress: '香港中環皇后大道中999號',
-        distance: '680米'
-    },
-    {
-        imgURL: require('../../assets/dummyStationPicture2.png'),
-        date: '4月20',
-        time: '12:30',
-        chargeStationName: '中環IFC充電站',
-        chargeStationAddress: '香港中環皇后大道中999號',
-        distance: '680米'
-    },
-    {
-        imgURL: require('../../assets/dummyStationPicture.png'),
-        date: '今天',
-        time: '16:30',
-        chargeStationName: '上環街市充電站',
-        chargeStationAddress: '香港上環皇后大道中345號',
-        distance: '400米'
-    },
-    {
-        imgURL: require('../../assets/dummyStationPicture.png'),
-        date: '今天',
-        time: '16:30',
-        chargeStationName: '上環街市充電站',
-        chargeStationAddress: '香港上環皇后大道中345號',
-        distance: '400米'
-    }
-];
+const ReservationLocationPage = () => {
+    const [stations, setStations] = useState([]);
+    const [TabItems, setTabItems] = useState<TabItem[]>([]);
 
-const LocationTabComponent: React.FC<TabViewComponentProps> = ({
-    titles,
-    tabItems
-}) => {
-    const layout = useWindowDimensions();
+    const LocationTabComponent: React.FC<TabViewComponentProps> = ({
+        titles,
+        tabItems
+    }) => {
+        const layout = useWindowDimensions();
 
-    const FirstRoute = () => (
-        <View style={{ flex: 1, backgroundColor: 'white' }}>
-            <FlashList
-                data={tabItems}
-                renderItem={({ item }) => {
-                    return (
-                        <Pressable
-                            // onPress={() => console.log('clicked')}
-                            onPress={() => router.push('resultDetailPage')}
-                            style={({ pressed }) => [
-                                styles.container,
-                                {
-                                    backgroundColor: pressed
-                                        ? '#e7f2f8'
-                                        : '#ffffff'
-                                }
-                            ]}
-                        >
-                            <View style={styles.container}>
-                                <Image
-                                    style={styles.image}
-                                    source={item.imgURL}
-                                />
-                                <View style={styles.textContainer}>
-                                    <Text
-                                        style={{
-                                            fontWeight: 400,
-                                            fontSize: 18,
-                                            color: '#222222'
-                                        }}
-                                    >
-                                        {item.chargeStationName}
-                                    </Text>
-                                    <Text
-                                        style={{
-                                            fontWeight: 400,
-                                            fontSize: 14,
-                                            color: '#888888'
-                                        }}
+        const FirstRoute = () => (
+            <View style={{ flex: 1, backgroundColor: 'white' }}>
+                {TabItems.length > 0 ? (
+                    <FlashList
+                        data={tabItems}
+                        renderItem={({ item }) => {
+                            return (
+                                <Pressable
+                                    onPress={() =>
+                                        router.push({
+                                            pathname: '/resultDetailPage',
+                                            params: {
+                                                chargeStationAddress:
+                                                    item.chargeStationAddress,
+                                                chargeStationName:
+                                                    item.chargeStationName,
+                                                chargeStationID: item.stationID
+                                            }
+                                        })
+                                    }
+                                    style={({ pressed }) => [
+                                        styles.container,
+                                        {
+                                            backgroundColor: pressed
+                                                ? '#e7f2f8'
+                                                : '#ffffff'
+                                        }
+                                    ]}
+                                >
+                                    <View
+                                        style={styles.container}
+                                        className=" flex-1 flex-row "
                                     >
-                                        {item.chargeStationAddress}
-                                    </Text>
-                                    <View className=" flex-row space-x-2  items-center">
-                                        <CheckMarkLogoSvg />
+                                        <Image
+                                            style={styles.image}
+                                            source={item.imgURL}
+                                        />
+                                        <View
+                                            style={styles.textContainer}
+                                            className="flex-1 justify-evenly"
+                                        >
+                                            <Text
+                                                style={{
+                                                    fontWeight: 400,
+                                                    fontSize: 20,
+                                                    color: '#222222'
+                                                }}
+                                            >
+                                                {item.chargeStationName}
+                                            </Text>
+                                            <Text
+                                                style={{
+                                                    fontWeight: 400,
+                                                    fontSize: 14,
+                                                    color: '#888888'
+                                                }}
+                                            >
+                                                {item.chargeStationAddress}
+                                            </Text>
+                                            <View className=" flex-row space-x-2  items-center">
+                                                <CheckMarkLogoSvg />
+                                                <Text
+                                                    style={{
+                                                        fontWeight: 400,
+                                                        fontSize: 14,
+                                                        color: '#222222'
+                                                    }}
+                                                >
+                                                    Walk-in
+                                                </Text>
+                                            </View>
+                                        </View>
+
                                         <Text
                                             style={{
                                                 fontWeight: 400,
-                                                fontSize: 14,
-                                                color: '#222222'
+                                                fontSize: 16,
+                                                color: '#888888',
+                                                marginTop: 22,
+                                                marginLeft: 'auto',
+                                                marginRight: 10
                                             }}
                                         >
-                                            Walk-in
+                                            {item.distance}
                                         </Text>
                                     </View>
-                                </View>
-                                <Text
-                                    style={{
-                                        fontWeight: 400,
-                                        fontSize: 16,
-                                        color: '#888888',
-                                        marginTop: 22
-                                    }}
-                                >
-                                    {item.distance}
-                                </Text>
-                            </View>
-                        </Pressable>
-                    );
-                }}
-                estimatedItemSize={10}
-            />
-        </View>
-    );
+                                </Pressable>
+                            );
+                        }}
+                        estimatedItemSize={10}
+                    />
+                ) : (
+                    <View className="flex-1 items-center justify-center">
+                        <ActivityIndicator size="large" />
+                    </View>
+                )}
+            </View>
+        );
 
-    //tab 2
+        //tab 2
 
-    const SecondRoute = () => (
-        <View style={{ flex: 1, backgroundColor: 'white' }}>
-            <FlashList
-                data={tabItems}
-                renderItem={({ item }) => {
-                    return (
-                        <Pressable
-                            // onPress={() => console.log('clicked')}
-                            onPress={() => router.push('resultDetailPage')}
-                            style={({ pressed }) => [
-                                styles.container,
-                                {
-                                    backgroundColor: pressed
-                                        ? '#e7f2f8'
-                                        : '#ffffff'
+        const SecondRoute = () => (
+            <View style={{ flex: 1, backgroundColor: 'white' }}>
+                <FlashList
+                    data={tabItems}
+                    renderItem={({ item }) => {
+                        return (
+                            <Pressable
+                                onPress={() =>
+                                    router.push({
+                                        pathname: '/resultDetailPage',
+                                        params: {
+                                            chargeStationAddress:
+                                                item.chargeStationAddress,
+                                            chargeStationName:
+                                                item.chargeStationName
+                                        }
+                                    })
                                 }
-                            ]}
-                        >
-                            <View style={styles.container}>
-                                <Image
-                                    style={styles.image}
-                                    source={item.imgURL}
-                                />
-                                <View style={styles.textContainer}>
-                                    <Text
-                                        style={{
-                                            fontWeight: 400,
-                                            fontSize: 18,
-                                            color: '#222222'
-                                        }}
-                                    >
-                                        {item.chargeStationName}
-                                    </Text>
-                                    <Text
-                                        style={{
-                                            fontWeight: 400,
-                                            fontSize: 14,
-                                            color: '#888888'
-                                        }}
+                                style={({ pressed }) => [
+                                    styles.container,
+                                    {
+                                        backgroundColor: pressed
+                                            ? '#e7f2f8'
+                                            : '#ffffff'
+                                    }
+                                ]}
+                            >
+                                <View
+                                    style={styles.container}
+                                    className=" flex-1 flex-row "
+                                >
+                                    <Image
+                                        style={styles.image}
+                                        source={item.imgURL}
+                                    />
+                                    <View
+                                        style={styles.textContainer}
+                                        className="flex-1 justify-evenly"
                                     >
-                                        {item.chargeStationAddress}
-                                    </Text>
-                                    <View className=" flex-row space-x-2  items-center">
-                                        <CheckMarkLogoSvg />
                                         <Text
                                             style={{
                                                 fontWeight: 400,
-                                                fontSize: 14,
+                                                fontSize: 20,
                                                 color: '#222222'
                                             }}
                                         >
-                                            Walk-in
+                                            {item.chargeStationName}
                                         </Text>
+                                        <Text
+                                            style={{
+                                                fontWeight: 400,
+                                                fontSize: 14,
+                                                color: '#888888'
+                                            }}
+                                        >
+                                            {item.chargeStationAddress}
+                                        </Text>
+                                        <View className=" flex-row space-x-2  items-center">
+                                            <CheckMarkLogoSvg />
+                                            <Text
+                                                style={{
+                                                    fontWeight: 400,
+                                                    fontSize: 14,
+                                                    color: '#222222'
+                                                }}
+                                            >
+                                                Walk-in
+                                            </Text>
+                                        </View>
                                     </View>
+
+                                    <Text
+                                        style={{
+                                            fontWeight: 400,
+                                            fontSize: 16,
+                                            color: '#888888',
+                                            marginTop: 22,
+                                            marginLeft: 'auto',
+                                            marginRight: 10
+                                        }}
+                                    >
+                                        {item.distance}
+                                    </Text>
                                 </View>
-                                <Text
-                                    style={{
-                                        fontWeight: 400,
-                                        fontSize: 16,
-                                        color: '#888888',
-                                        marginTop: 22
-                                    }}
-                                >
-                                    {item.distance}
-                                </Text>
-                            </View>
-                        </Pressable>
-                    );
+                            </Pressable>
+                        );
+                    }}
+                    estimatedItemSize={10}
+                />
+            </View>
+        );
+
+        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',
+                    borderColor: '#DBE4E8',
+                    elevation: 0,
+                    borderBottomWidth: 0.5
                 }}
-                estimatedItemSize={10}
             />
-        </View>
-    );
-    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);
+        );
+        return (
+            <TabView
+                navigationState={{ index, routes }}
+                renderScene={renderScene}
+                onIndexChange={setIndex}
+                // initialLayout={{ width: layout.width }}
+                renderTabBar={renderTabBar}
+            />
+        );
+    };
 
-    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',
-                borderColor: '#DBE4E8',
-                elevation: 0,
-                borderBottomWidth: 0.5
-            }}
-        />
-    );
-    return (
-        <TabView
-            navigationState={{ index, routes }}
-            renderScene={renderScene}
-            onIndexChange={setIndex}
-            initialLayout={{ width: layout.width }}
-            renderTabBar={renderTabBar}
-        />
-    );
-};
+    const styles = StyleSheet.create({
+        container: { flexDirection: 'row' },
+        image: {
+            width: 100,
+            height: 100,
+            marginTop: 15,
+            marginRight: 15,
+            borderRadius: 10
+        },
+        textContainer: { flexDirection: 'column', gap: 4, marginTop: 15 }
+    });
 
-const styles = StyleSheet.create({
-    container: { flexDirection: 'row' },
-    image: {
-        width: 100,
-        height: 100,
-        marginTop: 15,
-        marginRight: 15,
+    useEffect(() => {
+        const fetchStations = async () => {
+            const fetchedStations =
+                await chargeStationService.fetchChargeStations();
+          
+            setStations(fetchedStations);
 
-        borderRadius: 10
-    },
-    textContainer: { flexDirection: 'column', gap: 8, marginTop: 22 }
-});
+            const TabItems = fetchedStations.map((station) => ({
+                chargeStationAddress: station.Address,
+                chargeStationName: station.StationName,
+                date: '今天',
+                stationID: station.StationID,
+                imgURL: require('../../assets/dummyStationPicture.png'),
+                distance: '400米'
+            }));
+            setTabItems(TabItems);
+        };
+        fetchStations();
+    }, []);
 
-const ReservationLocationPage = () => {
     return (
         <SafeAreaView
             className="flex-1 bg-white"
@@ -339,7 +366,7 @@ const ReservationLocationPage = () => {
                 <View className="flex-1 mt-2">
                     <LocationTabComponent
                         titles={['附近的充電站', '所有的充電站']}
-                        tabItems={dummyTabItems}
+                        tabItems={TabItems}
                     />
                 </View>
             </View>
@@ -347,4 +374,4 @@ const ReservationLocationPage = () => {
     );
 };
 
-export default ReservationLocationPage;
+export default ReservationLocationPage;

+ 30 - 8
component/resultDetailPage/resultDetailPageComponent.tsx

@@ -7,17 +7,18 @@ import {
     StyleSheet,
     Pressable
 } from 'react-native';
-import React from 'react';
+import React, { useEffect, useState } from 'react';
 
 import { SceneMap, TabBar, TabView } from 'react-native-tab-view';
 import NormalButton from '../global/normal_button';
-import { router } from 'expo-router';
+import { router, useLocalSearchParams } from 'expo-router';
 import {
     CheckMarkLogoSvg,
     DirectionLogoSvg,
     PreviousPageSvg
 } from '../global/SVG';
 import { SafeAreaView } from 'react-native-safe-area-context';
+import { chargeStationService } from '../../service/chargeStationService';
 
 interface ChargingStationTabViewProps {
     titles: string[];
@@ -100,6 +101,25 @@ const ChargingStationTabView: React.FC<ChargingStationTabViewProps> = ({
 };
 
 const ResultDetailPageComponent = () => {
+    const params = useLocalSearchParams();
+    const chargeStationID = params.chargeStationID as string;
+    const [price, setPrice] = useState('');
+    useEffect(() => {
+        const fetchPrice = async () => {
+            try {
+                const price =
+                    await chargeStationService.fetchChargeStationPrice(
+                        chargeStationID
+                    );
+                setPrice(price);
+                // Do something with the price, like setting it to state
+            } catch (error) {
+                console.error('Error fetching price:', error);
+            }
+        };
+        fetchPrice();
+    }, []);
+
     return (
         <SafeAreaView
             edges={['top', 'left', 'right']}
@@ -129,14 +149,16 @@ const ResultDetailPageComponent = () => {
 
                 <View className="flex-column mx-[5%] mt-[5%]">
                     <View>
-                        <Text className="text-3xl">上環街市充電站</Text>
+                        <Text className="text-3xl">
+                            {params.chargeStationName}
+                        </Text>
                     </View>
                     <View className="flex-row justify-between items-center">
                         <Text
                             className="text-base"
                             style={{ color: '#888888' }}
                         >
-                            香港上環皇后大道中345號
+                            {params.chargeStationAddress}
                         </Text>
                         <NormalButton
                             title={
@@ -149,15 +171,15 @@ const ResultDetailPageComponent = () => {
                             extendedStyle={{
                                 backgroundColor: '#E3F2F8',
                                 borderRadius: 61,
-                                paddingHorizontal: 30,
+                                paddingHorizontal: 20,
                                 paddingVertical: 10
                             }}
                         />
                     </View>
-                    <View className="flex-row space-x-2 items-center pb-6 ">
+                    <View className="flex-row space-x-2 items-center pb-3 ">
                         <CheckMarkLogoSvg />
                         <Text>Walk-In</Text>
-                        <Text>400</Text>
+                        <Text>400m</Text>
                     </View>
                     <NormalButton
                         title={
@@ -207,7 +229,7 @@ const ResultDetailPageComponent = () => {
                                     <View className="flex-1"></View>
                                     <View className="flex-row items-center ml-4 space-x-2 ">
                                         <Text className="text-3xl text-[#02677D]">
-                                            $3.5
+                                            ${price}
                                         </Text>
                                         <Text style={styles.text}>每度電</Text>
                                     </View>

+ 15 - 4
component/searchPage/searchPageComponent.tsx

@@ -94,9 +94,19 @@ const SearchPageComponent: React.FC<SearchPageComponentProps> = () => {
             setFilteredItems(filteredData);
         }
     }, [searchInput]);
+
+
+
+
+
+    
     return (
-        <SafeAreaView className="flex-1 bg-white">
-            <ScrollView className=" flex-1 px-[5%] pt-6 ">
+        <SafeAreaView
+            edges={['top', 'right', 'left']}
+            className="flex-1 bg-white"
+        >
+            <ScrollView className=" flex-1 mx-[5%] pt-6 "
+            showsVerticalScrollIndicator={false}>
                 <View className="flex-column gap-4 ">
                     <View className=" flex-1 flex-row ">
                         <Pressable
@@ -285,8 +295,9 @@ const styles = StyleSheet.create({
         justifyContent: 'center'
     },
     textInput: {
-        width: '85%',
-        maxWidth: '100%',
+        // width: '100',
+        // maxWidth: '100%',
+        flex:1,
         fontSize: 16,
         padding: 20,
         paddingLeft: 0,

+ 142 - 0
service/chargeStationService.tsx

@@ -0,0 +1,142 @@
+import axios from 'axios';
+import { Alert } from 'react-native';
+import * as SecureStore from 'expo-secure-store';
+import { EXPO_PUBLIC_API_URL } from '@env';
+import { forgetPasswordFormData } from '../types/signup';
+import { CustomerData } from '../types/signUpFormData';
+
+class ChargeStationService {
+    private apiUrl: string;
+
+    constructor() {
+        this.apiUrl = EXPO_PUBLIC_API_URL;
+        if (!this.apiUrl) {
+            throw new Error('API URL is not defined in environment variables');
+        }
+    }
+
+    async fetchChargeStations() {
+        try {
+            const response = await axios.get(
+                `${this.apiUrl}/clients/chargestations/resources/info`,
+                {
+                    headers: {
+                        Authorization: `Bearer ${await SecureStore.getItemAsync(
+                            'accessToken'
+                        )}`
+                    }
+                }
+            );
+
+            if (response.status === 200 || response.status === 201) {
+                return response.data.data.map((station, index) => {
+                    const { Address, StationName, StationID } =
+                        station.snapshot;
+
+                    return { Address, StationName, StationID };
+                });
+            } else {
+                console.log('invalid response');
+            }
+        } catch (error) {
+            if (axios.isAxiosError(error)) {
+                console.error(
+                    'Login error:',
+                    error.response?.data?.message || error.message
+                );
+            } else {
+                console.error('An unexpected error occurred:', error);
+            }
+            return false;
+        }
+    }
+
+    async fetchChargeStationPrice(stationID: string) {
+        try {
+            const response = await axios.get(
+                `${this.apiUrl}/clients/promotion/price?id=${stationID}`
+            );
+            if (response.status === 200 || response.status === 201) {
+                return response.data.price;
+            } else {
+                console.log('invalid response');
+            }
+        } catch (error) {
+            if (axios.isAxiosError(error)) {
+                console.error(
+                    'Login error:',
+                    error.response?.data?.message || error.message
+                );
+            } else {
+                console.error('An unexpected error occurred:', error);
+            }
+            return false;
+        }
+    }
+
+    async fetchAvailableDates(stationID: string) {
+        try {
+            const response = await axios.get(
+                `${this.apiUrl}/clients/reservation/connectors/${stationID}`,
+                {
+                    headers: {
+                        Authorization: `Bearer ${await SecureStore.getItemAsync(
+                            'accessToken'
+                        )}`
+                    }
+                }
+            );
+            if (response.status === 200 || response.status === 201) {
+                const dates = response.data.map((i) => i.date);
+                return dates;
+            } else {
+                console.log('invalid response');
+            }
+        } catch (error) {
+            if (axios.isAxiosError(error)) {
+                console.error(
+                    'Login error:',
+                    error.response?.data?.message || error.message
+                );
+            } else {
+                console.error('An unexpected error occurred:', error);
+            }
+            return false;
+        }
+    }
+
+    async fetchAvailableTimeSlots(stationID: string, targetDate: string) {
+        try {
+            const response = await axios.get(
+                `${this.apiUrl}/clients/reservation/connectors/${stationID}`,
+                {
+                    headers: {
+                        Authorization: `Bearer ${await SecureStore.getItemAsync(
+                            'accessToken'
+                        )}`
+                    }
+                }
+            );
+            if (response.status === 200 || response.status === 201) {
+                const times = response.data.find((i) => i.date === targetDate);
+                if (times) {
+                    const availableTimeSlots = times.range.map((i) => i.start);
+                    return availableTimeSlots;
+                }
+            } else {
+                console.log('invalid response');
+            }
+        } catch (error) {
+            if (axios.isAxiosError(error)) {
+                console.error(
+                    'Login error:',
+                    error.response?.data?.message || error.message
+                );
+            } else {
+                console.error('An unexpected error occurred:', error);
+            }
+            return false;
+        }
+    }
+}
+export const chargeStationService = new ChargeStationService();