149 lines
3.9 KiB
TypeScript
149 lines
3.9 KiB
TypeScript
import { StationProps } from "@/lib/CommonTypes";
|
||
import { lightColors } from "@/lib/theme";
|
||
import { MaterialCommunityIcons, Ionicons, FontAwesome5 } from "@expo/vector-icons";
|
||
import { FC } from "react";
|
||
import {
|
||
Linking,
|
||
Text,
|
||
TouchableOpacity,
|
||
useWindowDimensions,
|
||
View,
|
||
} from "react-native";
|
||
|
||
type Props = {
|
||
item: StationProps[];
|
||
isCurrentStation: boolean;
|
||
};
|
||
|
||
/** 観光スポット向け看板コンポーネント(テーマパーク風) */
|
||
export const SpotSign: FC<Props> = ({ item, isCurrentStation }) => {
|
||
const { width } = useWindowDimensions();
|
||
|
||
const cardWidth = width * 0.8;
|
||
const cardHeight = (cardWidth / 20) * 9;
|
||
|
||
const displayName = item[0].Station_JP.startsWith(".")
|
||
? item[0].Station_JP.slice(1)
|
||
: item[0].Station_JP;
|
||
|
||
// テーマパーク風のグラデーション帯カラー
|
||
const accentColor = "#e67e22"; // オレンジ
|
||
const accentDark = "#c0392b"; // 深紅
|
||
|
||
return (
|
||
<View
|
||
style={{
|
||
width: cardWidth,
|
||
height: cardHeight,
|
||
borderWidth: 2,
|
||
borderColor: accentColor,
|
||
backgroundColor: "#fff8f0",
|
||
overflow: "hidden",
|
||
}}
|
||
>
|
||
{/* 上部カラフル帯 */}
|
||
<View
|
||
style={{
|
||
position: "absolute",
|
||
top: 0,
|
||
left: 0,
|
||
right: 0,
|
||
height: "22%",
|
||
backgroundColor: accentDark,
|
||
flexDirection: "row",
|
||
alignItems: "center",
|
||
paddingHorizontal: 8,
|
||
gap: 4,
|
||
}}
|
||
>
|
||
<FontAwesome5 name="torii-gate" size={cardHeight * 0.11} color="#FFD700" />
|
||
<Text
|
||
style={{
|
||
color: "#FFD700",
|
||
fontSize: cardHeight * 0.1,
|
||
fontWeight: "bold",
|
||
letterSpacing: 1,
|
||
}}
|
||
>
|
||
観光スポット
|
||
</Text>
|
||
{isCurrentStation && (
|
||
<MaterialCommunityIcons
|
||
name="crosshairs-gps"
|
||
color="white"
|
||
size={cardHeight * 0.12}
|
||
style={{ marginLeft: 4 }}
|
||
/>
|
||
)}
|
||
</View>
|
||
|
||
{/* スポット名(中央) */}
|
||
<View
|
||
style={{
|
||
position: "absolute",
|
||
top: "22%",
|
||
left: 0,
|
||
right: 0,
|
||
bottom: "28%",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
paddingHorizontal: 8,
|
||
}}
|
||
>
|
||
<Text
|
||
style={{
|
||
fontSize: cardHeight * 0.28,
|
||
fontWeight: "bold",
|
||
color: "#2c3e50",
|
||
letterSpacing: displayName.length < 4 ? cardHeight * 0.04 : 0,
|
||
}}
|
||
adjustsFontSizeToFit
|
||
numberOfLines={1}
|
||
>
|
||
{displayName}
|
||
</Text>
|
||
<Text
|
||
style={{
|
||
fontSize: cardHeight * 0.09,
|
||
color: "#7f8c8d",
|
||
marginTop: 2,
|
||
}}
|
||
>
|
||
{item[0].Station_EN}
|
||
</Text>
|
||
</View>
|
||
|
||
{/* 下部オレンジ帯(マップ・Webリンク) */}
|
||
<View
|
||
style={{
|
||
position: "absolute",
|
||
bottom: 0,
|
||
left: 0,
|
||
right: 0,
|
||
height: "28%",
|
||
backgroundColor: accentColor,
|
||
flexDirection: "row",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
gap: 16,
|
||
}}
|
||
>
|
||
<TouchableOpacity
|
||
onPress={() => item[0].StationMap && Linking.openURL(item[0].StationMap)}
|
||
hitSlop={{ top: 8, bottom: 8, left: 12, right: 12 }}
|
||
>
|
||
<Ionicons name="map-outline" size={cardHeight * 0.15} color="white" />
|
||
</TouchableOpacity>
|
||
{item[0].JrHpUrl ? (
|
||
<TouchableOpacity
|
||
onPress={() => Linking.openURL(item[0].JrHpUrl)}
|
||
hitSlop={{ top: 8, bottom: 8, left: 12, right: 12 }}
|
||
>
|
||
<MaterialCommunityIcons name="web" size={cardHeight * 0.15} color="white" />
|
||
</TouchableOpacity>
|
||
) : null}
|
||
</View>
|
||
</View>
|
||
);
|
||
};
|