jrshikoku/components/trainMenu.js
2024-05-27 16:39:15 +00:00

261 lines
7.9 KiB
JavaScript

import React, { useRef, useState, useEffect } from "react";
import { View, Text, TouchableOpacity, Linking, Platform } from "react-native";
import MapView, { Marker } from "react-native-maps";
import Constants from "expo-constants";
import { MaterialCommunityIcons, Ionicons } from "@expo/vector-icons";
import { useCurrentTrain } from "../stateBox/useCurrentTrain";
import { useNavigation } from "@react-navigation/native";
import lineColorList from "../assets/originData/lineColorList";
import { stationIDPair } from "../lib/getStationList2";
import { lineListPair } from "../lib/getStationList";
import { SheetManager } from "react-native-actions-sheet";
import { useTrainMenu } from "../stateBox/useTrainMenu";
export default function TrainMenu({ stationData, style }) {
const { webview } = useCurrentTrain();
const mapRef = useRef();
const { navigate } = useNavigation();
const [stationPin, setStationPin] = useState([]);
const { selectedLine, setSelectedLine } = useTrainMenu();
useEffect(() => {
const stationPinData = [];
Object.keys(stationData).map((d, indexBase) =>
stationData[d].map((D, index) => {
if (!D.StationMap) return null;
if (selectedLine && selectedLine != d) return;
const latlng = D.StationMap.replace(
"https://www.google.co.jp/maps/place/",
""
).split(",");
if (latlng.length == 0) return null;
stationPinData.push({ D, d, latlng, indexBase: 0, index });
})
);
setStationPin(stationPinData);
}, [stationData, selectedLine]);
useEffect(() => {
mapRef.current.fitToCoordinates(
stationPin.map(({ latlng }) => ({
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
})),
{ edgePadding: { top: 100, bottom: 50, left: 50, right: 50 } } // Add margin values here
);
}, [stationPin]);
return (
<View style={{ height: "100%", backgroundColor: "#0099CC", ...style }}>
<MapView
style={{ flex: 1, width: "100%", height: "100%" }}
showsUserLocation={true}
loadingEnabled={true}
showsMyLocationButton={false}
moveOnMarkerPress={false}
showsCompass={false}
ref={mapRef}
//provider={PROVIDER_GOOGLE}
initialRegion={{
latitude: 33.774519,
longitude: 133.533306,
latitudeDelta: 1.8, //小さくなるほどズーム
longitudeDelta: 1.8,
}}
>
{stationPin.map(({ D, d, latlng, indexBase, index }) => (
<MapPin
index={index}
indexBase={indexBase}
latlng={latlng}
D={D}
d={d}
navigate={navigate}
webview={webview}
key={index + indexBase}
/>
))}
</MapView>
<View style={{ position: "relative" }}>
<View
style={{
flexDirection: "row",
position: "absolute",
width: "100vw",
bottom: 0,
flex: 1,
}}
>
<TouchableOpacity
style={{
backgroundColor: selectedLine
? lineColorList[stationIDPair[selectedLine]]
: "#0099CC",
padding: 10,
zIndex: 1,
alignItems: "center",
position: "absolute",
bottom: 0,
width: "100%",
paddingBottom: 50,
}}
onPress={() => SheetManager.show("TrainMenuLineSelector")}
>
<Text
style={{
color: "white",
fontWeight: "bold",
fontSize: 20,
textAlign: "center",
}}
>
{selectedLine
? lineListPair[stationIDPair[selectedLine]]
: "ここを押して路線をフィルタリングできます  ▲"}
</Text>
</TouchableOpacity>
<Text style={{ position: "absolute", bottom: 40 }}>
路線記号からフィルタリング
</Text>
{Object.keys(stationData).map((d) => (
<TouchableOpacity
style={{
flex: 1,
backgroundColor: lineColorList[stationIDPair[d]],
padding: 5,
margin: 2,
borderRadius: 10,
borderColor: "white",
borderWidth: 1,
borderStyle: "solid",
alignItems: "center",
opacity: selectedLine == d ? 1 : !selectedLine ? 1 : 0.5,
zIndex: 10,
}}
onPress={() => setSelectedLine(selectedLine == d ? undefined : d)}
>
<Text
style={{ color: "white", fontWeight: "bold", fontSize: 20 }}
>
{stationIDPair[d]}
</Text>
</TouchableOpacity>
))}
</View>
</View>
{navigate && (
<View style={{ flexDirection: "row" }}>
<UsefulBox
backgroundColor={"#F89038"}
icon="train-car"
flex={1}
onPressButton={() =>
navigate("howto", {
info: "https://train.jr-shikoku.co.jp/usage.htm",
})
}
>
使い方
</UsefulBox>
<UsefulBox
backgroundColor={"#EA4752"}
icon="star"
flex={1}
onPressButton={() => navigate("favoriteList")}
>
お気に入り
</UsefulBox>
<UsefulBox
backgroundColor={"#91C31F"}
icon="clipboard-list-outline"
flex={1}
onPressButton={() =>
Linking.openURL(
"https://nexcloud.haruk.in/apps/forms/ZRHjWFF7znr5Xjr2"
)
}
>
フィードバック
</UsefulBox>
</View>
)}
<MapsButton
onPress={() => navigate("Apps")}
top={Platform.OS == "ios" ? Constants.statusBarHeight : 0}
mapSwitch={"flex"}
/>
</View>
);
}
const UsefulBox = (props) => {
const { icon, backgroundColor, flex, onPressButton, children } = props;
return (
<TouchableOpacity
style={{
flex: flex,
backgroundColor: backgroundColor,
padding: 5,
alignItems: "center",
margin: 2,
}}
onPress={onPressButton}
>
<MaterialCommunityIcons name={icon} color="white" size={50} />
<Text style={{ color: "white", fontWeight: "bold", fontSize: 16 }}>
{children}
</Text>
</TouchableOpacity>
);
};
const MapPin = ({ index, indexBase, latlng, D, d, navigate, webview }) => {
return (
<Marker
key={index + indexBase}
coordinate={{
latitude: parseFloat(latlng[0]),
longitude: parseFloat(latlng[1]),
}}
onPress={() => {
webview.current?.injectJavaScript(
`MoveDisplayStation('${d}_${D.MyStation}_${D.Station_JP}');
document.getElementById("disp").insertAdjacentHTML("afterbegin", "<div />");`
);
if (navigate) navigate("Apps");
}}
></Marker>
);
};
const MapsButton = ({ onPress, top, mapSwitch }) => {
const styles = {
touch: {
position: "absolute",
top,
left: 10,
width: 50,
height: 50,
backgroundColor: "#0099CC",
borderColor: "white",
borderStyle: "solid",
borderWidth: 1,
borderRadius: 50,
alignContent: "center",
alignSelf: "center",
alignItems: "center",
display: mapSwitch,
},
text: {
textAlign: "center",
width: "auto",
height: "auto",
textAlignVertical: "center",
fontWeight: "bold",
color: "white",
},
};
return (
<TouchableOpacity onPress={onPress} style={styles.touch}>
<View style={{ flex: 1 }} />
<Ionicons name="close" color="white" size={30} />
<View style={{ flex: 1 }} />
</TouchableOpacity>
);
};