코딩하는 김딸기

RouteView.tsx(경로 리스트) 본문

카테고리 없음

RouteView.tsx(경로 리스트)

김딸기* 2024. 12. 16. 05:13

이 코드에서는 React Native를 사용하여 교통 경로를 검색하고 그에 대한 정보를 보여주는 애플리케이션의 주요 기능이 구현되어 있습니다. 주요 요소를 차례대로 설명드리겠습니다.

1. 상단 탭 및 탭 설정 (Tabs)

// 상단 탭에 아이콘 추가
const transTabs = [
  {label: '대중', icon: 'directions-transit'}, // 대중교통 아이콘
  {label: '택시', icon: 'local-taxi'}, // 택시 아이콘
  //{ label: '도보', icon: 'directions-walk' },      // 도보 아이콘
];

const tabs = [
  `택시+버스+지하철`,
  `택시+버스`,
  `택시+지하철`,
  `지하철+버스`,
  `지하철`,
  `버스`,
];
  • transTabs는 탭에 표시될 교통 수단에 대한 아이콘과 라벨을 정의합니다. 예를 들어, "대중"과 "택시" 탭을 정의합니다.
  • tabs는 사용자가 선택할 수 있는 경로의 유형을 정의하며, 각 경로 유형에 대한 조합(예: "택시+버스+지하철")이 나열되어 있습니다.

2. 상태 변수 (State Variables)

앱의 여러 상태를 관리하기 위한 변수들이 설정되어 있습니다. 주요 변수들은 다음과 같습니다:

  • loading: 로딩 상태를 관리 (API 호출 시 데이터 로딩 중인지 확인)
  • searchOriText, searchDestText: 출발지와 도착지 텍스트
  • selectedTransTab: 선택된 교통수단 탭 (택시/대중)
  • selectedTab: 선택된 경로 유형
  • departureTime, arrivalTime: 출발 및 도착 시간
  • startPosition, arrivalPosition: 출발지 및 도착지의 위도/경도
  • API 호출에 필요한 상태들 (publicRoutes, taxiRoutes, routes 등)

3. fetchRoutes 함수

API에서 경로 데이터를 가져오는 함수입니다. 사용자가 설정한 출발지, 도착지, 시간 등에 따라 API를 호출하여 교통 경로 데이터를 반환합니다.

  // API 호출을 위한 함수
  const fetchRoutes = async (
    startLongitude: any,
    startLatitude: any,
    endLongitude: any,
    endLatitude: any,
    nowTime: any,
    budget: any,
  ) => {
    //const dummyTIme = new Date(Date.now()).toISOString();
    const url = `http://54.92.160.65/api/dummy/${startLongitude},${startLatitude}/${endLongitude},${endLatitude}/${nowTime}/0`;
    setLoading(true);
    try {
      console.log('Requesting API with URL:', url);
      const response = await axios.get(url);
      //console.log("리퀘스트후데이터",response.data.taxiPublic);
      return response.data;
    } catch (error) {
      console.error('Error fetching routes:', error);
      return null;
    } finally {
      setLoading(false); // 로딩 상태 비활성화
    }
  };
  • axios.get(url)을 통해 API에서 경로 데이터를 요청합니다.
  • API 호출이 완료되면 response.data를 반환하고, 로딩 상태는 false로 설정합니다.

4. 경로 클릭 시 처리 (Handle Route Press)

사용자가 경로를 클릭하면 해당 경로의 상세 정보 페이지로 이동하게 됩니다.


  const handleRoutePress = (path: any, taxi: any, isTaxi: string) => {
    //console.log("상세",path);

    if (path) {
      setSelectedTaxi(taxi);
      setIsTaxi(isTaxi);
      setSelectedPath(path); // 클릭한 path를 Context에 저장
      navigation.navigate('PathDetails'); // 상세 페이지로 이동
    }
  };
  • 선택한 경로를 PathDetails 화면으로 넘겨 상세 정보를 표시합니다.

5. 출발지와 도착지 교체 (Swap Locations)

출발지와 도착지의 위치를 교체하는 함수입니다.

  // 출발지와 도착지를 교체하는 함수
  const swapLocations = () => {
    // 출발지와 도착지 텍스트 교체
    const tempText = searchOriText;
    setSearchOriText(searchDestText);
    setSearchDestText(tempText);

    // 출발지와 도착지 위도, 경도 교체
    const tempPosition = startPosition;
    setStartPosition(arrivalPosition);
    setArrivalPosition(tempPosition);

    // 교체 후 API 호출
    getRoutes();
  };
  • searchOriText와 searchDestText를 교환하여 텍스트를 업데이트합니다.
  • 출발지와 도착지의 위도/경도 값도 교환하고, getRoutes() 함수로 새로운 경로를 가져옵니다.

6. 출발 시간 및 도착 시간 처리 (Time Change)

사용자가 출발 시간과 도착 시간을 선택하면 해당 시간을 상태에 저장합니다.

  // 출발 시간 변경 처리
  const onDepartureTimeChange = (event: any, selectedTime: any) => {
    const currentTime = new Date(nowTime);
    currentTime.setHours(selectedTime.getHours()); // 선택된 시간으로 시간 설정
    currentTime.setMinutes(selectedTime.getMinutes()); // 선택된 시간으로 분 설정
    currentTime.setSeconds(0); // 초는 0으로 설정 (필요에 따라 수정 가능)

    setShowDeparturePicker(Platform.OS === 'ios'); // iOS에서는 계속 보여짐
    setDepartureTime(currentTime);
  };
  • 출발 시간을 변경하면 departureTime 상태를 업데이트합니다.
  • Platform.OS === 'ios'는 iOS에서 시간이 Picker로 계속 표시되도록 설정하는 코드입니다.

7. 시간 포맷 처리 (Time Formatting)

시간을 다양한 형식으로 변환하는 함수들이 정의되어 있습니다:

  • formatTime: 시간을 12시간 형식(AM/PM)으로 변환
  • formatTotalTime: 총 시간을 "X시간 Y분" 형식으로 변환

8. API 데이터 처리 (getRoutes 함수)

앱이 시작될 때 API 호출을 통해 출발지와 도착지, 현재 시간에 맞는 경로 데이터를 가져오는 함수입니다.


  // 경로 데이터를 API로부터 가져오는 함수 (앱 시작 시 한 번만 호출)
  const getRoutes = async () => {
    const startLongitude = startPosition?.longitude;
    const startLatitude = startPosition?.latitude;
    const endLongitude = arrivalPosition?.longitude;
    const endLatitude = arrivalPosition?.latitude;
    const nowTime2 = new Date(Date.now()).toISOString(); // 현재 시간
    const budget = 0; // 예산을 사용자가 설정한 값으로ㅊ
    console.log('나api요청했다');

    setLoading(true); // 로딩 상태 활성화

    const apiData = await fetchRoutes(
      startLongitude,
      startLatitude,
      endLongitude,
      endLatitude,
      nowTime2,
      budget,
    );
    // console.log('API 요청 파라미터:', {
    //   startLongitude: startPosition?.longitude,
    //   startLatitude: startPosition?.latitude,
    //   endLongitude: arrivalPosition?.longitude,
    //   endLatitude: arrivalPosition?.latitude,
    //   nowTime: new Date(Date.now()).toISOString(),
    // });
    //console.log('여기실행되나?제발!@!@!!@',apiData);

    if (apiData) {
      setPublicRoutes(apiData.public);
      setTaxiRoutes(apiData.taxiPublic.taxi);
      setTaxiPublicRoutes(apiData.taxiPublic);

      setMaxAmount(apiData.budget.toString());
      //console.log('나지금 택시퍼블릭 넣는다?',apiData.taxiPublic);
      if (selectedTransTab === '택시') {
        setRoutes(taxiPublicRoutes);
      } else if (selectedTransTab === '대중') {
        setRoutes(publicRoutes);
      }
    }

    setLoading(false); // 로딩 상태 비활성화
  };
  • API 응답 데이터를 받아와서 publicRoutes, taxiRoutes, taxiPublicRoutes에 저장합니다.
  • 사용자가 선택한 교통수단에 따라 표시할 경로 데이터를 설정합니다.

요약

이 코드는 출발지와 도착지를 입력받고, 선택된 교통수단에 맞는 경로를 API로부터 받아와 사용자에게 표시하는 기능을 구현합니다. 사용자는 출발 시간과 도착 시간을 설정하고, 탭을 통해 교통수단을 선택할 수 있습니다. 경로를 클릭하면 상세 페이지로 이동하여 해당 경로의 세부 정보를 볼 수 있습니다.


주어진 코드는 대중교통과 택시 경로를 관리하는 앱의 일부입니다. 이 코드는 다양한 탭(예: '대중' 대중교통 탭, '택시' 탭)에 따라 경로를 선택하고 필터링하는 로직을 포함하고 있으며, 도착 시간과 출발 시간을 기준으로 경로를 필터링하고, 경로를 시간 또는 비용 기준으로 정렬하는 기능도 포함되어 있습니다. 각 부분을 좀 더 이해하기 쉽게 나누어 설명하겠습니다.

1. 선택된 탭에 따라 경로 업데이트

  // 탭 변경 시 저장된 데이터에서 적절한 경로 데이터를 불러옴
  const updateRoutesByTransTab = (tab: any) => {
    if (tab === '대중') {
      console.log('대중 데이터:', publicRoutes); // 데이터
      setRoutes(publicRoutes);
    } else if (tab == '택시') {
      setRoutes(taxiPublicRoutes);
    }
  };
  • updateRoutesByTransTab 함수는 선택된 탭(tab)에 따라 적절한 경로 데이터를 설정합니다.
    • '대중' 탭에서는 publicRoutes를, '택시' 탭에서는 taxiPublicRoutes를 로드하여 setRoutes로 상태를 업데이트합니다.

2. 탭 변경 시 경로 업데이트 및 필터링


  useEffect(() => {
    updateRoutesByTransTab(selectedTransTab); // 탭이 변경될 때 저장된 데이터에서 경로를 업데이트
    if (selectedTransTab === '대중') {
      setSelectedTab('지하철+버스');
    } else if (selectedTransTab === '택시') {
      setSelectedTab('택시+버스+지하철');
    }
    getFilteredRoutes();
  }, [selectedTransTab]); // selectedTab이 변경될 때마다 실행
  • useEffect는 selectedTransTab이 변경될 때마다 호출됩니다. 탭에 맞는 경로를 업데이트하고, 그에 따라 기본 선택 탭을 설정한 후 필터링된 경로를 가져옵니다.

3. 출발 시간 변경 시 API 호출


  useEffect(() => {
    getRoutes(); // 출발시각 변경 시 한 번 API 호출 (더미 데이터를 통해)
    getFilteredRoutes();
  }, [departureTime]);
  • departureTime이 변경되면 새로운 경로를 가져오고, 변경된 출발 시간에 맞게 경로를 필터링합니다.

4. 경로 필터링

  const getFilteredRoutes = () => {
    console.log('겟라우트왔다일단');
    setFilteredRoutes([]);
    // routes가 undefined나 null일 경우 빈 배열로 처리
    // if (!routes || !Array.isArray(routes)) {
    //   console.log('대체 route가왜 이상한데',routes);
    //   return [];
    // }

    if (selectedTransTab === '택시') {
      // 각 route의 path 배열을 순회하여 필터링
      taxiPublicRoutes.map((route: any) => {
        // console.log('여긴됨22233?2323',route.public.path);
        // route.public.result.path가 배열인지 확인 후 필터링
        if (route.public.path) {
          const taxiFee = route.taxi.summary.taxiFare;

          //console.log('휘벌 여기어디여',route.public.path);
          const validPaths = route.public.path.filter((pathItem: any) => {
            const startTime = departureTime;
            const endTime = new Date(pathItem.info.arriveTime);
            const fee = taxiFee;

            if (arrivalTime) {
              arrivalTime.setDate(nowTime.getDate());

              if (startTime > arrivalTime) {
                arrivalTime.setDate(nowTime.getDate() + 1);
              }
            }
            //console.log('유저설정도착시간: ',arrivalTime);
            //console.log('진짜도착시간',endTime);

            // 필터링 조건: 출발/도착 시간, 금액 한도, 탭에 따른 type 필터링
            //console.log('유저가누른텝이름',selectedTab);
            const typeFilter = () => {
              if (
                selectedTab === '택시+버스+지하철' ||
                selectedTab === '지하철+버스'
              ) {
                return pathItem.pathType === 3;
              } else if (
                selectedTab === '택시+버스' ||
                selectedTab === '버스'
              ) {
                return pathItem.pathType === 2;
              } else if (
                selectedTab === '택시+지하철' ||
                selectedTab === '지하철'
              ) {
                return pathItem.pathType === 1;
              }
              return pathItem.pathType === 1; // 기본값
            };
            //꼭 arrivalTime 설정안할시 undefined나 null로 해주세요@@@@@@@@@@@@@@@@@@@@@@

            if (arrivalTime) {
              return (
                arrivalTime >= endTime &&
                fee <= Number(maxAmount) &&
                typeFilter()
              );
            }
            return fee <= Number(maxAmount) && typeFilter();
          });
          console.log('벨리드페쓰@@@@@@!', validPaths);
          //console.log('현재필터루트',filteredRoutes);

          // 필터링된 path가 있으면 해당 경로를 추가
          if (validPaths.length > 0) {
            //console.log('여기실행됨?');
            const newFilteredRoutes = validPaths.map((pathItem: any) => ({
              ...route,
              public: {
                ...route.public,
                path: pathItem, // 하나의 경로만 포함
              },
            }));
            //console.log('새로만든놈!',newFilteredRoute);

            // 기존 filteredRoutes 배열을 복사한 후 새로운 경로를 추가
            setFilteredRoutes(prevRoutes => {
              const updatedRoutes = [...prevRoutes, ...newFilteredRoutes];
              console.log(
                '업데이트된 루트2:',
                updatedRoutes.map(item => item.public.path.pathType),
              ); // 상태 업데이트 후 확인
              return updatedRoutes; // 상태에 반영
            });
          }
          //console.log('이후필터루트',filteredRoutes);
        }
      });
      //console.log('필터링ㅈ된루트위쪽@@@@@@!',filteredRoutes);
      // 정렬 옵션 처리
      setFilteredRoutes(prevRoutes => {
        if (sortOption === '최소비용') {
          return [...prevRoutes].sort((a, b) => {
            const feeA = extractFee(
              a.public.path.info.payment + a.taxi.summary.taxiFare,
            );
            const feeB = extractFee(
              b.public.path.info.payment + b.taxi.summary.taxiFare,
            );
            return feeA - feeB; // 비용 오름차순
          });
        } else if (sortOption === '최소시간') {
          return [...prevRoutes].sort((a, b) => {
            const timeA = a.public.path.info.totalTime;
            const timeB = b.public.path.info.totalTime;
            return timeA - timeB; // 시간 오름차순
          });
        }
        return prevRoutes;
      });
    } else if (selectedTransTab === '대중') {
      // 각 route의 path 배열을 순회하여 필터링
      console.log('시발내가왜이걸하고있지', publicRoutes);

      // console.log('여긴됨22233?2323',route.public.path);
      // route.public.result.path가 배열인지 확인 후 필터링
      if (publicRoutes && publicRoutes.path) {
        const validPaths = publicRoutes.path.filter((pathItem: any) => {
          const startTime = departureTime;
          const endTime = new Date(pathItem.info.arriveTime);
          // console.log("우으",pathItem.info);

          if (arrivalTime) {
            arrivalTime.setDate(nowTime.getDate());

            if (startTime > arrivalTime) {
              arrivalTime.setDate(nowTime.getDate() + 1);
            }
          }

          const typeFilter = () => {
            if (
              selectedTab === '택시+버스+지하철' ||
              selectedTab === '지하철+버스'
            ) {
              return pathItem.pathType === 3;
            } else if (selectedTab === '택시+버스' || selectedTab === '버스') {
              return pathItem.pathType === 2;
            } else if (
              selectedTab === '택시+지하철' ||
              selectedTab === '지하철'
            ) {
              return pathItem.pathType === 1;
            }
            return pathItem.pathType === 1; // 기본값
          };

          if (arrivalTime) {
            return arrivalTime >= endTime && typeFilter();
          }
          return typeFilter();
        });
        console.log('대중벨리드폐흐22ㄸ@#@#', validPaths);

        if (validPaths.length > 0) {
          const newFilteredRoutes = validPaths.map((pathItem: any) => ({
            ...publicRoutes,
            path: pathItem,
          }));
          console.log('뉴우우', newFilteredRoutes);
          setFilteredRoutes(prevRoutes => {
            const updatedRoutes = [...prevRoutes, ...newFilteredRoutes];
            console.log(
              '업데이트된 대중2루트2:',
              updatedRoutes.map(item => item.path.pathType),
            ); // 상태 업데이트 후 확인
            return updatedRoutes; // 상태에 반영
          });
        }
      }
      // console.log('필터링ㅈ된루트위쪽@@@@@@!',filteredRoutes);
      // 정렬 옵션 처리
      setFilteredRoutes(prevRoutes => {
        if (sortOption === '최소비용') {
          return [...prevRoutes].sort((a, b) => {
            const feeA = extractFee(a.path.info.payment);
            const feeB = extractFee(b.path.info.payment);
            return feeA - feeB; // 비용 오름차순
          });
        } else if (sortOption === '최소시간') {
          return [...prevRoutes].sort((a, b) => {
            const timeA = a.path.info.totalTime;
            const timeB = b.path.info.totalTime;
            return timeA - timeB; // 시간 오름차
          });
        }
        return prevRoutes;
      });
    }
  };
  • getFilteredRoutes 함수는 택시와 대중교통 경로를 각각 필터링하여, 선택된 탭(selectedTab), 출발 시간(departureTime), 도착 시간(arrivalTime), 금액(maxAmount)에 맞는 경로를 필터링합니다. 이후 필터링된 경로를 상태에 업데이트합니다.
  • 추가적으로, 경로는 최소 비용 또는 최소 시간을 기준으로 정렬됩니다.

5. 역 아이콘 설정

  //역별 아이콘을 결정하는 함수 (아이콘을 반환)
  const getStationIcon = (tftype: number) => {
    // 특정 호선에 따라 아이콘 설정 (예: 2호선)
    if (tftype === 1) {
      return <Icon name="directions-subway" size={20} color="#28cadc" />;
    } else if (tftype === 2) {
      return <Icon name="directions-bus" size={20} color="#4CAF50" />;
    }

    // 기본 아이콘 설정 (기타 호선)
    //return <Icon name="local-taxi" size={20} color="#000"/>
  };
  • getStationIcon 함수는 tftype 값에 따라 지하철 또는 버스 아이콘을 반환합니다.

6. 역 정보 렌더링


  // 경유 역을 렌더링하는 함수
  const renderStation = ({item, index}: any) => {
    // wayCode 값에 따른 상행/하행 변환
    const wayDirection = (wayCode: number) => {
      if (wayCode === 1) return '상행';
      if (wayCode === 2) return '하행';
      return '알 수 없음';
    };

    // subwayClass 값에 따른 지하철 종류 변환
    const subwayClassType = (subwayClass: number) => {
      if (subwayClass === 0) return '일반';
      if (subwayClass === 1) return '급행';
      if (subwayClass === 2) return '특급';
      return '알 수 없음';
    };

    // busArrivalInfo 배열에서 첫 두 개의 값만 가져옴
    const getLimitedBusInfo = (busArrivalInfo: any[]) => {
      //console.log("버스시간",busArrivalInfo);
      if (!busArrivalInfo || busArrivalInfo.length === 0) return [];

      // 최대 두 개의 버스 도착 정보를 표시
      return busArrivalInfo.slice(0, 2);
    };

    return (
      <View style={styles.stationItem}>
        {getStationIcon(item.trafficType)}
        <View style={{marginLeft: 10}}>
          {item.trafficType === 1 && (
            <>
              <Text style={styles.station}>{item.startName}</Text>
              <Text style={styles.subInfo}>
                {item.departureTime} | {item.way} | {wayDirection(item.wayCode)}{' '}
                | {subwayClassType(item.subwayClass)}
              </Text>
            </>
          )}

          {item.trafficType === 2 && (
            <>
              <Text style={styles.station}>{item.startName} 정류장</Text>

              {item.busArrivalInfo && item.busArrivalInfo.length > 0 ? (
                getLimitedBusInfo(item.busArrivalInfo).map(
                  (busInfo, busIndex) => (
                    <View key={busIndex}>
                      {(busInfo.arrival1 &&
                        Object.keys(busInfo.arrival1).length > 0) ||
                      (busInfo.arrival2 &&
                        Object.keys(busInfo.arrival2).length > 0) ? ( // arrival1이나 arrival2 중 하나라도 유효한 경우
                        <Text style={styles.subInfo}>
                          {busInfo.routeNm} |
                          {busInfo.arrival1 &&
                          formatBusTime(busInfo.arrival1.arrivalSec) != 0
                            ? ` ${formatBusTime(
                                busInfo.arrival1.arrivalSec,
                              )}${busInfo.arrival1.leftStation}정류장`
                            : ` 잠시 후 ${busInfo.arrival1.leftStation}정류장`}
                          {busInfo.arrival1 && busInfo.arrival2 && '  '}
                          {busInfo.arrival2 &&
                            `${formatBusTime(busInfo.arrival2.arrivalSec)}${
                              busInfo.arrival2.leftStation
                            }정류장`}
                        </Text>
                      ) : (
                        <Text style={styles.subInfo}>도착 예정 정보 없음</Text>
                      )}
                    </View>
                  ),
                )
              ) : (
                // busArrivalInfo가 없을 때
                <Text style={styles.subInfo}>도착 예정 정보 없음</Text>
              )}
            </>
          )}
        </View>
      </View>
    );
  };
  • renderStation 함수는 각 역의 정보를 렌더링하는 함수로, 지하철 방향(wayDirection), 급행 여부(subwayClassType), 버스 정보(getLimitedBusInfo) 등을 처리합니다.

이 코드는 사용자가 선택한 탭과 다양한 조건에 따라 대중교통과 택시 경로를 효과적으로 필터링하고 정렬하는 방식으로 설계되었습니다.


이 코드는 교통 수단의 정보를 표시하고, 사용자가 특정 설정을 할 수 있도록 하는 React Native 코드입니다. 코드의 기능을 여러 부분으로 나누어 설명드리겠습니다.

1. stationItem 컴포넌트

이 부분은 각 교통 수단(지하철 또는 버스)의 정보를 화면에 표시하는 부분입니다.

1.1 지하철 정보 (trafficType === 1)

 return (
      <View style={styles.stationItem}>
        {getStationIcon(item.trafficType)}
        <View style={{marginLeft: 10}}>
          {item.trafficType === 1 && (
            <>
              <Text style={styles.station}>{item.startName}</Text>
              <Text style={styles.subInfo}>
                {item.departureTime} | {item.way} | {wayDirection(item.wayCode)}{' '}
                | {subwayClassType(item.subwayClass)}
              </Text>
            </>
          )}
  • item.trafficType === 1인 경우, 즉 교통 수단이 지하철일 경우:
    • startName (출발 역 이름)을 표시합니다.
    • departureTime, way, wayDirection, subwayClassType 등 출발 시간, 경로, 방향, 클래스 유형을 표시합니다.

1.2 버스 정보 (trafficType === 2)

{item.trafficType === 2 && (
            <>
              <Text style={styles.station}>{item.startName} 정류장</Text>

              {item.busArrivalInfo && item.busArrivalInfo.length > 0 ? (
                getLimitedBusInfo(item.busArrivalInfo).map(
                  (busInfo, busIndex) => (
                    <View key={busIndex}>
                      {(busInfo.arrival1 &&
                        Object.keys(busInfo.arrival1).length > 0) ||
                      (busInfo.arrival2 &&
                        Object.keys(busInfo.arrival2).length > 0) ? ( // arrival1이나 arrival2 중 하나라도 유효한 경우
                        <Text style={styles.subInfo}>
                          {busInfo.routeNm} |
                          {busInfo.arrival1 &&
                          formatBusTime(busInfo.arrival1.arrivalSec) != 0
                            ? ` ${formatBusTime(
                                busInfo.arrival1.arrivalSec,
                              )}${busInfo.arrival1.leftStation}정류장`
                            : ` 잠시 후 ${busInfo.arrival1.leftStation}정류장`}
                          {busInfo.arrival1 && busInfo.arrival2 && '  '}
                          {busInfo.arrival2 &&
                            `${formatBusTime(busInfo.arrival2.arrivalSec)}${
                              busInfo.arrival2.leftStation
                            }정류장`}
                        </Text>
                      ) : (
                        <Text style={styles.subInfo}>도착 예정 정보 없음</Text>
                      )}
                    </View>
                  ),
                )
              ) : (
                // busArrivalInfo가 없을 때
                <Text style={styles.subInfo}>도착 예정 정보 없음</Text>
              )}
            </>
          )}
  • item.trafficType === 2인 경우, 즉 교통 수단이 버스일 경우:
    • startName (버스 정류장 이름)을 표시합니다.
    • busArrivalInfo 배열이 있는 경우, 각 버스 도착 정보(arrival1, arrival2)를 표시합니다.
    • formatBusTime 함수는 버스의 도착 시간을 포맷팅합니다.
    • 도착 정보가 없으면 "도착 예정 정보 없음"을 표시합니다.

2. 탭 선택 (handleTabPress 및 handleTransTabPress)

 const handleTabPress = (tab: string) => {
    setSelectedTab(tab);
  };
  const handleTransTabPress = (tab: string) => {
    setSelectedTransTab(tab);
  };
  • handleTabPress: 교통 수단 종류(지하철, 버스 등) 탭을 클릭하면 해당 탭을 활성화시킵니다.
  • handleTransTabPress: 추가적인 탭(예: 교통 수단 종류) 클릭 시 해당 탭을 활성화시킵니다.

3. 검색 및 위치 교환 (출발지, 도착지)

  return (
    <View style={styles.container}>
      {loading && (
        <TouchableWithoutFeedback>
          <View style={styles.loadingOverlay}>
            <ActivityIndicator size="large" color="#0000ff" />
          </View>
        </TouchableWithoutFeedback>
      )}
      <FlatList
        data={filteredRoutes}
        extraData={filteredRoutes}
        keyExtractor={(item, index) => `${item.id}-${index}`}
        ListHeaderComponent={
          <>
            {/* 검색창 */}
            <View style={styles.searchContainer}>
              <View style={styles.transTabContainer}>
                {transTabs.map(tab => (
                  <TouchableOpacity
                    key={tab.label}
                    onPress={() => handleTransTabPress(tab.label)}
                    style={[
                      styles.tab,
                      selectedTransTab === tab.label && styles.selectedTransTab, // 선택된 탭 강조
                    ]}>
                    {/* 아이콘 추가 */}
                    <Icon
                      name={tab.icon}
                      size={25}
                      color={
                        selectedTransTab === tab.label ? '#4CE5B1' : '#fff'
                      } // 선택된 탭은 초록색, 나머지는 흰색
                    />
                  </TouchableOpacity>
                ))}
              </View>

              {/* 출발지와 도착지 입력 및 교체 버튼 */}
              <View style={styles.searchInputContainer}>
                <View style={styles.changeContainer}>
                  <Text style={styles.searchInput}>{searchOriText}</Text>
                  {/* 교체 버튼 */}
                  <TouchableOpacity
                    style={styles.swapButton}
                    onPress={swapLocations}>
                    <Icon name="swap-vert" size={25} color="#fff" />
                  </TouchableOpacity>
                </View>
                <View style={styles.optionContainer}>
                  <Text style={styles.searchInput}>{searchDestText}</Text>
                  <TouchableOpacity style={styles.addButton}>
                    <Icon name="more-vert" size={25} color="#fff" />
                  </TouchableOpacity>
                </View>
              </View>
            </View>
  • 사용자는 출발지와 도착지를 입력합니다.
  • swapLocations: 교환 버튼을 클릭하면 출발지와 도착지의 위치를 바꿉니다.

4. 교통수단 탭 필터 (transTabs 및 탭 렌더링)

{/* 교통수단 탭 */}
            <View style={styles.tabsContainer}>
              {getFilteredTabs().map(tab => (
                <TouchableOpacity
                  key={tab}
                  onPress={() => handleTabPress(tab)}
                  style={[
                    styles.tab,
                    selectedTab === tab && styles.selectedTab, // 선택된 탭 강조!
                  ]}>
                  <Text
                    style={[
                      styles.tabText,
                      selectedTab === tab && styles.selectedTab,
                    ]}>
                    {tab}
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
  • transTabs: 교통수단 종류(예: 지하철, 버스) 필터를 위한 탭입니다.
  • 사용자가 탭을 클릭하면 handleTransTabPress 함수가 호출되어 선택된 탭이 강조 표시됩니다.

5. 출발시간 및 도착시간 설정 (DateTimePicker)

<View style={styles.settingForms}>
              {/* 하단의 출발시간, 도착시간 설정 부분 (Time Picker 사용) */}
              <View style={styles.settingsContainer}>
                <View style={{flexDirection: 'row'}}>
                  <TouchableOpacity
                    onPress={() => setShowDeparturePicker(true)}
                    style={styles.settingItem}>
                    <View>
                      <Text style={styles.settingInput}>
                        {formatTime(departureTime)}
                      </Text>
                    </View>
                    <Text style={styles.settingLabel}>출발</Text>
                    <View>
                      <Icon2
                        name="triangle-down"
                        size={20}
                        style={styles.settingIcon}
                      />
                    </View>
                    {showDeparturePicker && (
                      <DateTimePicker
                        value={departureTime}
                        mode="time"
                        is24Hour={false}
                        display="spinner"
                        onChange={onDepartureTimeChange}
                      />
                    )}
                  </TouchableOpacity>
  • 사용자는 출발 시간과 도착 시간을 설정할 수 있습니다.
  • DateTimePicker: 시간을 선택할 수 있는 UI 컴포넌트입니다.
  • onDepartureTimeChange: 사용자가 출발 시간을 변경하면 호출되는 함수입니다.
  • formatTime: 시간을 지정된 포맷으로 출력합니다.

6. 로딩 인디케이터

jsx
코드 복사
{loading && ( <TouchableWithoutFeedback> <View style={styles.loadingOverlay}> <ActivityIndicator size="large" color="#0000ff" /> </View> </TouchableWithoutFeedback> )}
  • loading이 true일 경우, 로딩 중임을 나타내는 ActivityIndicator가 화면에 표시됩니다.

7. FlatList로 데이터 렌더링

jsx
코드 복사
<FlatList data={filteredRoutes} extraData={filteredRoutes} keyExtractor={(item, index) => `${item.id}-${index}`} ListHeaderComponent={/* 검색창, 탭, 시간 설정 부분 */} />
  • filteredRoutes 배열에 있는 교통 정보를 FlatList로 렌더링합니다.
  • keyExtractor: 각 항목을 고유하게 식별하는 키를 설정합니다.
  • ListHeaderComponent: 리스트의 상단에 표시될 컴포넌트(검색창, 탭 등)를 설정합니다.

요약

이 코드는 교통 수단의 정보를 효과적으로 보여주는 UI를 구성하며, 사용자가 출발지, 도착지, 교통수단 등을 선택하고 설정할 수 있는 기능을 제공합니다. 각 교통수단별로 정보를 렌더링하고, 다양한 필터링 옵션과 시간 설정 기능을 제공합니다.


이 코드는 교통 경로를 보여주는 React Native 컴포넌트의 일부로, 사용자에게 금액 한도와 정렬 옵션을 설정하고, 그에 맞는 경로 정보를 표시하는 구조입니다. 각 부분을 자세히 설명하겠습니다.

1. 금액 한도 설정 및 정렬 옵션

<View style={{flexDirection: 'row'}}>
                  {/* 금액 설정 */}
                  <View style={styles.settingItem}>
                    <Text style={styles.sortSectionLabel}>금액 한도</Text>
                    <TextInput
                      style={styles.input}
                      keyboardType="numeric"
                      value={maxAmount}
                      onChangeText={setMaxAmount}
                    />
                    <Text style={styles.sortSectionLabel}></Text>
                    <View>
                      <Icon2
                        name="triangle-down"
                        size={20}
                        style={styles.settingIcon}
                      />
                    </View>
                  </View>
                  <View style={styles.settingItem}>
                    <Picker
                      selectedValue={sortOption}
                      style={styles.picker}
                      onValueChange={itemValue => setSortOption(itemValue)}>
                      <Picker.Item
                        label="정렬"
                        value="정렬"
                        style={styles.pickerItem}
                      />
                      <Picker.Item
                        label="최소 비용"
                        value="최소비용"
                        style={styles.pickerItem}
                      />
                      <Picker.Item
                        label="최소 시간"
                        value="최소시간"
                        style={styles.pickerItem}
                      />
                    </Picker>
                  </View>
                </View>
              </View>
            </View>
          </>
        }
  • 금액 한도를 설정하는 TextInput 컴포넌트가 있습니다. 사용자는 금액 한도를 입력할 수 있습니다.
  • Picker를 사용하여 정렬 옵션을 설정할 수 있습니다. 사용자 선택에 따라 최소 비용, 최소 시간 등의 옵션을 선택할 수 있습니다.
  • Icon2는 드롭다운 화살표 아이콘을 표시하여 추가적인 UI 요소로 보입니다.

2. 경로 정보 렌더링

renderItem={({item}: any) => {
          const currentPath = selectedTransTab === '대중' ? item : item?.public;
          const taxiFare =
            selectedTransTab === '택시' ? item?.taxi?.summary?.taxiFare : 0;
          // if(selectedTransTab==='대중'){
          //   console.log("대중",currentPath);
          // }

          return (
            <TouchableOpacity
              style={styles.routeContainer}
              onPress={() =>
                handleRoutePress(currentPath?.path, item, selectedTransTab)
              }>
              <View style={styles.routeContainer}>
                {/* item.public.path가 단일 객체이므로 배열로 가정하지 않음 */}
                {currentPath && (
                  <>
                    {/* 경로 정보 헤더 */}
                    <View style={styles.routeHeader}>
                      <Text style={styles.duration}>
                        {formatTotalTime(currentPath?.path?.info?.totalTime)}
                      </Text>
                      {(selectedTab === '택시+버스+지하철' ||
                        selectedTab === '택시+버스' ||
                        selectedTab === '택시+지하철') && (
                        <Text style={styles.savings}>{item.ecoScore} 절약</Text>
                      )}
                    </View>
                    {/* 경로 세부 정보 */}
                    <View style={styles.routeDetails}>
                      <Text style={styles.fee}>
                        {departureTime.toLocaleTimeString('ko-KR', {
                          hour: '2-digit',
                          minute: '2-digit',
                        })}{' '}
                        ~{' '}
                        {new Date(
                          currentPath?.path?.info?.arriveTime,
                        ).toLocaleTimeString('ko-KR', {
                          hour: '2-digit',
                          minute: '2-digit',
                        })}
                      </Text>
                      <Text style={styles.fee}>|</Text>
                      <Text style={styles.fee}>
                        {currentPath?.path?.info?.payment + taxiFare}
                      </Text>
                    </View>
                    {/* 정거장 정보 */}
                    <View style={styles.stationsContainer}>
                      {/* 택시 이동 정보 표시 */}
                      {(selectedTab === '택시+버스+지하철' ||
                        selectedTab === '택시+버스' ||
                        selectedTab === '택시+지하철') && (
                        <View style={styles.stationItem}>
                          <Icon name="local-taxi" size={20} color="#000" />
                          <Text style={styles.taxiStation}>택시로 이동 </Text>
                          <Text style={styles.subInfo}>{taxiFare}</Text>
                        </View>
                      )}
                      {/* 지하철 또는 버스 경로 정보 렌더링 */}
                      {currentPath?.path?.info?.subPath?.map(
                        (subPath: any, subIndex: number) => (
                          <View key={subIndex}>
                            {renderStation({item: subPath, subIndex})}
                          </View>
                        ),
                      )}
                    </View>
                  </>
                )}
              </View>
            </TouchableOpacity>
          );
        }}
      />
    </View>
  );
};
  • renderItem: 각 교통 경로 항목을 렌더링하는 함수입니다.
    • currentPath: 선택된 탭(예: 대중교통, 택시)에 따라 보여줄 경로를 선택합니다.
    • taxiFare: 택시 요금이 선택된 경우, item?.taxi?.summary?.taxiFare에서 택시 요금을 가져옵니다.
  • 각 경로는 TouchableOpacity로 감싸져 있어, 클릭 시 handleRoutePress 함수가 호출되며 경로 정보를 보여줍니다.

2.1 경로 정보 헤더

  • duration: 전체 경로 소요 시간을 포맷팅하여 표시합니다.
  • ecoScore: 선택된 탭에 따라 ecoScore (환경 점수)를 표시합니다.

2.2 경로 세부 정보

  • 출발 시간과 도착 시간을 표시하고, 이를 기반으로 전체 소요 시간도 표시합니다.
  • payment + taxiFare: 교통 경로의 총 요금(버스/지하철 요금과 택시 요금을 합산한 값)을 표시합니다.

2.3 정거장 정보

  • 선택된 탭에 따라 택시 이동 정보를 표시합니다.
  • 지하철 또는 버스 경로(subPath)가 존재하면 이를 반복문으로 렌더링하여 각 경로의 정보를 표시합니다.

3. FlatList와의 연동

위의 renderItem 함수는 FlatList의 renderItem prop에 사용됩니다. 이로 인해, 각 경로 항목을 리스트 형식으로 렌더링합니다. FlatList는 데이터의 항목을 반복적으로 렌더링할 때 효율적이므로 많은 데이터를 처리할 때 유용합니다.

요약

이 코드는 교통 경로를 표시하는 UI로, 사용자가 금액 한도와 정렬 옵션을 설정할 수 있는 기능을 제공합니다. 사용자가 선택한 경로(택시, 대중교통 등)에 따라 각 경로의 소요 시간, 요금, 절약된 환경 점수 등을 표시하며, 각 경로는 클릭할 수 있어 상세 정보를 볼 수 있습니다. FlatList를 사용하여 여러 경로를 효율적으로 렌더링합니다.