133 lines
4.4 KiB
TypeScript
133 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, { useEffect, useMemo, useState } from "react";
|
|
import { router, useLocalSearchParams } from "expo-router";
|
|
import { usePersonContext } from "@/contexts/PersonContext";
|
|
import {
|
|
ScrollView,
|
|
GestureHandlerRootView,
|
|
} from "react-native-gesture-handler";
|
|
import { useShowContext } from "@/contexts/ShowContext";
|
|
import { getPersonHistory } from "@/apis/personApi";
|
|
|
|
export default function ParticipantScreen() {
|
|
const { getPersonAppearances, isLoading, getError } = usePersonContext();
|
|
const [appearances, setAppearances] = useState<
|
|
{
|
|
showId: number;
|
|
seasons: number[];
|
|
}[]
|
|
>([]);
|
|
const { shows, error, loading } = useShowContext();
|
|
const { participantId, name, season } = useLocalSearchParams();
|
|
const numericId = Array.isArray(participantId)
|
|
? Number(participantId[0])
|
|
: Number(participantId);
|
|
|
|
useEffect(() => {
|
|
let active = true;
|
|
(async () => {
|
|
if (!numericId || Number.isNaN(numericId)) return;
|
|
const data = await getPersonAppearances(numericId);
|
|
if (!active) return;
|
|
const grouped = data.showIds.map((id) => ({
|
|
showId: id,
|
|
seasons: data.byShow[id],
|
|
}));
|
|
setAppearances(grouped);
|
|
})();
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, [numericId, getPersonAppearances]);
|
|
|
|
const resolved = useMemo(
|
|
() =>
|
|
appearances
|
|
.map((a) => {
|
|
const show = shows.find((s) => s.id === a.showId);
|
|
if (!show) return null;
|
|
return { show, seasons: a.seasons };
|
|
})
|
|
.filter(
|
|
(v): v is { show: (typeof shows)[number]; seasons: number[] } => !!v
|
|
),
|
|
[appearances, shows]
|
|
);
|
|
|
|
return (
|
|
<GestureHandlerRootView style={styles.mainContainer}>
|
|
<ScrollView showsVerticalScrollIndicator={false}>
|
|
<Text style={styles.participantName}>
|
|
{name ? (Array.isArray(name) ? name[0] : name) : "Teilnehmer"}
|
|
</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>
|
|
{isLoading(numericId) && (
|
|
<Text style={{ color: "white", marginTop: 8 }}>Lädt...</Text>
|
|
)}
|
|
{getError(numericId) && (
|
|
<Text style={{ color: "tomato", marginTop: 8 }}>
|
|
{getError(numericId)}
|
|
</Text>
|
|
)}
|
|
{!isLoading(numericId) &&
|
|
resolved.length === 0 &&
|
|
!getError(numericId) && (
|
|
<Text style={{ color: "gray", marginTop: 8 }}>
|
|
Keine Einträge.
|
|
</Text>
|
|
)}
|
|
<ScrollView
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
style={{
|
|
width: "100%",
|
|
marginTop: 15,
|
|
}}
|
|
>
|
|
{resolved.map(({ show, seasons }) => (
|
|
<TouchableOpacity key={show.id} style={styles.showContainer}>
|
|
<Image
|
|
source={{ uri: show.thumbnailUri }}
|
|
style={styles.showImage}
|
|
/>
|
|
<Text style={styles.showTitle} numberOfLines={2}>
|
|
{show.title}
|
|
</Text>
|
|
<Text style={styles.showSeason} numberOfLines={1}>
|
|
Staffel
|
|
{seasons.length === 1
|
|
? ` ${seasons[0]}`
|
|
: `n ${seasons.join(", ")}`}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
</ScrollView>
|
|
</GestureHandlerRootView>
|
|
);
|
|
}
|