Files
fltr-app/app/participant.tsx
2025-10-07 16:14:11 +02:00

145 lines
4.4 KiB
TypeScript

import { View, Image, Text, TouchableOpacity } from "react-native";
import styles from "@/app/stackStyles/participantStyles";
import Ionicons from "@expo/vector-icons/Ionicons";
import React, {
useCallback,
useMemo,
useRef,
useEffect,
useState,
} from "react";
import { router } from "expo-router";
import Feather from "@expo/vector-icons/Feather";
import BottomSheet, { BottomSheetScrollView } from "@gorhom/bottom-sheet";
import {
ScrollView,
GestureHandlerRootView,
} from "react-native-gesture-handler";
import { useShowContext } from "@/contexts/ShowContext";
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withRepeat,
withSequence,
Easing,
cancelAnimation,
} from "react-native-reanimated";
export default function ParticipantScreen() {
const { shows, error, loading } = useShowContext();
const bottomSheetRef = useRef<BottomSheet>(null);
const [sheetIndex, setSheetIndex] = useState(1);
const handleSheetChange = useCallback((index: number) => {
setSheetIndex(index);
}, []);
const snapPoints = useMemo(() => ["10%", "10%", "45%"], []);
const bounce = useSharedValue(0);
const expanded = useSharedValue(0);
useEffect(() => {
if (sheetIndex === 2) {
cancelAnimation(bounce);
expanded.value = withTiming(1, { duration: 120 });
bounce.value = withTiming(-12, { duration: 120 });
} else {
expanded.value = withTiming(0, { duration: 100 });
bounce.value = withRepeat(
withSequence(
withTiming(-6, { duration: 250, easing: Easing.out(Easing.quad) }),
withTiming(0, { duration: 250, easing: Easing.inOut(Easing.quad) })
),
-1,
true
);
}
return () => {
cancelAnimation(bounce);
};
}, [sheetIndex, bounce, expanded]);
const iconAnimatedStyle = useAnimatedStyle(() => ({
transform: [
{ translateY: bounce.value },
{ rotate: `${expanded.value * 180}deg` },
],
opacity: 1 - expanded.value * 0.3,
}));
return (
<GestureHandlerRootView style={styles.mainContainer}>
<ScrollView showsVerticalScrollIndicator={false}>
<Text style={styles.participantName}>Calvin Ogara</Text>
<TouchableOpacity
style={styles.closeIcon}
onPress={() => router.back()}
>
<Ionicons name="close-circle-outline" size={38} color="white" />
</TouchableOpacity>
<View style={styles.participantInfoSection}>
<Text style={styles.participantInfo}>Single</Text>
<View style={styles.dot} />
<Text style={styles.participantInfo}>24 Jahre</Text>
<View style={styles.dot} />
<Text style={styles.participantInfo}>Köln</Text>
</View>
<Image
source={{
uri: "https://www.fernseh-puls.com/wp-content/uploads/are-you-the-one-calvin-o-im-steckbrief-wir-stellen-euch-den-kandidaten-vor.jpg",
}}
style={styles.participantImage}
/>
<View style={styles.performedShowsSection}>
<Text style={styles.performedShowsTitle}>Auftritte:</Text>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={{
width: "100%",
marginTop: 15,
}}
>
{shows.map((show, i) => (
<View style={styles.showContainer} key={i}>
<Image
source={{ uri: show.thumbnailUri }}
style={styles.showImage}
/>
</View>
))}
</ScrollView>
</View>
<BottomSheet
ref={bottomSheetRef}
index={1}
snapPoints={snapPoints}
enableDynamicSizing={false}
onChange={handleSheetChange}
backgroundStyle={{ backgroundColor: "hsl(221, 39%, 12%)" }}
handleIndicatorStyle={{ backgroundColor: "transparent" }}
>
<BottomSheetScrollView
contentContainerStyle={styles.contentContainer}
>
<Animated.View
style={[
{ alignSelf: "center", marginBottom: 20 },
iconAnimatedStyle,
]}
>
<Feather name="chevrons-up" size={40} color="white" />
</Animated.View>
</BottomSheetScrollView>
</BottomSheet>
</ScrollView>
</GestureHandlerRootView>
);
}