209 lines
6.6 KiB
TypeScript
209 lines
6.6 KiB
TypeScript
import StackHeader from "@/components/ui/StackHeader";
|
|
import { useLocalSearchParams, router } from "expo-router";
|
|
import ShowInfo from "@/components/ui/ShowInfo";
|
|
import ParticipantDetails from "@/components/ParticipantDeatails";
|
|
import React from "react";
|
|
import { useSeasonContext } from "@/contexts/SeasonContext";
|
|
import {
|
|
Dimensions,
|
|
Image,
|
|
ScrollView,
|
|
Text,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import * as WebBrowser from "expo-web-browser";
|
|
import styles from "./stackStyles/showDetailStyles";
|
|
|
|
export default function ShowDetails() {
|
|
const { bannerUri, description, concept, genres, streamingService, id } =
|
|
useLocalSearchParams();
|
|
const [selectedParticipants, setSelectedParticipants] =
|
|
React.useState<boolean>(true);
|
|
const [selectedSeason, setSelectedSeason] = React.useState<number>(1);
|
|
const showId = Number(id);
|
|
const { fetchSeasonParticipants, fetchSeasonCount } = useSeasonContext();
|
|
const [seasonCount, setSeasonCount] = React.useState<number>(0);
|
|
const [participants, setParticipants] = React.useState<
|
|
{ id: number; name: string; imageUri: string }[]
|
|
>([]);
|
|
const [pLoading, setPLoading] = React.useState(false);
|
|
const [pError, setPError] = React.useState<string | null>(null);
|
|
|
|
React.useEffect(() => {
|
|
if (!showId) return;
|
|
let active = true;
|
|
(async () => {
|
|
const count = await fetchSeasonCount(showId);
|
|
if (active) {
|
|
setSeasonCount(count);
|
|
if (count > 0 && selectedSeason > count) setSelectedSeason(1);
|
|
}
|
|
})();
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, [showId, fetchSeasonCount]);
|
|
|
|
React.useEffect(() => {
|
|
if (!showId || !selectedSeason) return;
|
|
let active = true;
|
|
(async () => {
|
|
setPError(null);
|
|
setPLoading(true);
|
|
try {
|
|
const data = await fetchSeasonParticipants(showId, selectedSeason);
|
|
if (active) setParticipants(data);
|
|
} catch {
|
|
if (active) setPError("Fehler beim Laden");
|
|
} finally {
|
|
if (active) setPLoading(false);
|
|
}
|
|
})();
|
|
return () => {
|
|
active = false;
|
|
};
|
|
}, [showId, selectedSeason, fetchSeasonParticipants]);
|
|
|
|
return (
|
|
<View style={styles.mainContainer}>
|
|
<StackHeader />
|
|
<ScrollView
|
|
showsVerticalScrollIndicator={false}
|
|
contentContainerStyle={{
|
|
paddingBottom: Dimensions.get("window").height * 0.1,
|
|
}}
|
|
>
|
|
<Image
|
|
source={{
|
|
uri: "https://images.plus.rtl.de/watch/859291/artwork_square/c3-ni-th-jc/are-you-the-one",
|
|
}}
|
|
style={styles.showImage}
|
|
/>
|
|
<ShowInfo
|
|
seasons={seasonCount}
|
|
participants={participants.length}
|
|
streamingService={streamingService as string}
|
|
/>
|
|
|
|
<View style={styles.showBannerLogoContainer}>
|
|
<Image
|
|
source={{
|
|
uri: bannerUri as string,
|
|
}}
|
|
style={styles.showBannerLogo}
|
|
resizeMode="cover"
|
|
/>
|
|
</View>
|
|
<View style={styles.infoContainner}>
|
|
<TouchableOpacity onPress={() => setSelectedParticipants(true)}>
|
|
<Text
|
|
style={[
|
|
styles.infoLabel,
|
|
{
|
|
fontWeight: selectedParticipants ? "bold" : "normal",
|
|
color: selectedParticipants ? "#199edb" : "hsl(0, 0%, 65%)",
|
|
},
|
|
]}
|
|
>
|
|
Teilnehmer
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity onPress={() => setSelectedParticipants(false)}>
|
|
<Text
|
|
style={[
|
|
styles.infoLabel,
|
|
{
|
|
fontWeight: !selectedParticipants ? "bold" : "normal",
|
|
color: !selectedParticipants ? "#199edb" : "hsl(0, 0%, 65%)",
|
|
},
|
|
]}
|
|
>
|
|
Details
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
{selectedParticipants ? (
|
|
<>
|
|
<View style={styles.seasonsSection}>
|
|
<Text style={styles.seasonsLabel}>Staffeln</Text>
|
|
<ScrollView
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={styles.seasonList}
|
|
>
|
|
{Array.from({ length: seasonCount }, (_, idx) => idx + 1).map(
|
|
(season) => (
|
|
<TouchableOpacity
|
|
key={season}
|
|
style={[
|
|
styles.seasonContainer,
|
|
{
|
|
backgroundColor:
|
|
selectedSeason === season
|
|
? "#199edb"
|
|
: "hsl(0, 0%, 20%)",
|
|
},
|
|
]}
|
|
onPress={() => setSelectedSeason(season)}
|
|
>
|
|
<Text style={styles.seasonLabel}>{season}</Text>
|
|
</TouchableOpacity>
|
|
)
|
|
)}
|
|
</ScrollView>
|
|
</View>
|
|
|
|
<View
|
|
style={[
|
|
styles.participantsDetailsContainer,
|
|
styles.participantSection,
|
|
]}
|
|
>
|
|
{pError && (
|
|
<Text style={{ color: "tomato", marginBottom: 8 }}>
|
|
{pError}
|
|
</Text>
|
|
)}
|
|
{!pLoading && !pError && participants.length === 0 && (
|
|
<Text style={{ color: "gray" }}>Keine Teilnehmer.</Text>
|
|
)}
|
|
{participants.map((p) => (
|
|
<TouchableOpacity
|
|
key={p.id}
|
|
style={styles.participantContainer}
|
|
onPress={() =>
|
|
router.push({
|
|
pathname: "/participant",
|
|
params: { participantId: p.id, name: p.name },
|
|
})
|
|
}
|
|
>
|
|
<Image
|
|
source={{ uri: p.imageUri }}
|
|
style={{
|
|
width: "100%",
|
|
height: "100%",
|
|
borderRadius: 10,
|
|
}}
|
|
/>
|
|
<Text style={styles.participantLabel} numberOfLines={2}>
|
|
{p.name}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
))}
|
|
</View>
|
|
</>
|
|
) : (
|
|
<ParticipantDetails
|
|
description={description as string}
|
|
concept={concept as string}
|
|
genres={genres as string}
|
|
streamingService={streamingService as string}
|
|
/>
|
|
)}
|
|
</ScrollView>
|
|
</View>
|
|
);
|
|
}
|