245 lines
7.6 KiB
TypeScript
245 lines
7.6 KiB
TypeScript
import styles from "@/app/tabStyles/indexStyles";
|
|
import ShowCard from "@/components/ui/ShowCard";
|
|
import { useShows } from "@/hooks/useShows";
|
|
import { useStreamingServices } from "@/hooks/useStreamingServices";
|
|
import * as Haptics from "expo-haptics";
|
|
import { router } from "expo-router";
|
|
import React from "react";
|
|
import {
|
|
ActivityIndicator,
|
|
Image,
|
|
Text,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import {
|
|
GestureHandlerRootView,
|
|
ScrollView,
|
|
} from "react-native-gesture-handler";
|
|
|
|
export default function HomeScreen() {
|
|
const { data: shows = [], error, isLoading: loading } = useShows();
|
|
const { data: streamingServices = {} } = useStreamingServices();
|
|
const [activeFilter, setActiveFilter] = React.useState<string>("all");
|
|
|
|
const haptikFeedback = () => {
|
|
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
|
};
|
|
|
|
const handleFilter = (type: string) => {
|
|
haptikFeedback();
|
|
if (type === activeFilter) {
|
|
setActiveFilter("all");
|
|
} else {
|
|
setActiveFilter(type);
|
|
}
|
|
};
|
|
|
|
const filteredShows = React.useMemo(() => {
|
|
if (activeFilter === "all") {
|
|
return shows;
|
|
}
|
|
if (activeFilter === "live") {
|
|
return shows.filter((show) => show.running);
|
|
}
|
|
return shows.filter((show) =>
|
|
show.streamingService
|
|
.split(",")
|
|
.map((s) => s.trim())
|
|
.includes(activeFilter)
|
|
);
|
|
}, [shows, activeFilter]);
|
|
|
|
const uniqueStreamingServices = React.useMemo(() => {
|
|
const uniqueServices = new Set<string>();
|
|
shows.forEach((show) => {
|
|
const services = show.streamingService.split(", ").map((s) => s.trim());
|
|
services.forEach((service) => uniqueServices.add(service));
|
|
});
|
|
return Array.from(uniqueServices);
|
|
}, [shows]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<View
|
|
style={[
|
|
styles.mainContainer,
|
|
{ justifyContent: "center", alignItems: "center" },
|
|
]}
|
|
>
|
|
<ActivityIndicator size="large" color="#ffffff" />
|
|
</View>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<View
|
|
style={[
|
|
styles.mainContainer,
|
|
{ justifyContent: "center", alignItems: "center" },
|
|
]}
|
|
>
|
|
<Text>Error: {error?.message || String(error)}</Text>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<GestureHandlerRootView>
|
|
<View style={styles.mainContainer}>
|
|
<View style={styles.header}>
|
|
<Text style={styles.title}>FLTR</Text>
|
|
</View>
|
|
<ScrollView
|
|
contentContainerStyle={{ paddingBottom: 30 }}
|
|
showsHorizontalScrollIndicator={false}
|
|
>
|
|
<View style={styles.filterSection}>
|
|
<ScrollView
|
|
horizontal
|
|
showsHorizontalScrollIndicator={false}
|
|
contentContainerStyle={{
|
|
alignItems: "center",
|
|
paddingHorizontal: 10,
|
|
gap: 10,
|
|
marginLeft: 10,
|
|
}}
|
|
>
|
|
{activeFilter !== "all" && (
|
|
<TouchableOpacity
|
|
style={{
|
|
padding: 5,
|
|
height: 60,
|
|
width: 60,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
backgroundColor: "hsla(0, 0%, 29%, 1.00)",
|
|
borderRadius: 50,
|
|
}}
|
|
onPress={() => handleFilter("all")}
|
|
>
|
|
<Text style={{ fontWeight: "bold", color: "white" }}>
|
|
ALLE
|
|
</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
{activeFilter !== "live" && (
|
|
<TouchableOpacity
|
|
style={{
|
|
padding: 5,
|
|
height: 60,
|
|
width: 60,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
backgroundColor: "hsla(0, 0%, 29%, 1.00)",
|
|
borderRadius: 50,
|
|
}}
|
|
onPress={() => handleFilter("live")}
|
|
>
|
|
<View
|
|
style={{
|
|
backgroundColor: "red",
|
|
paddingHorizontal: 5,
|
|
paddingVertical: 2,
|
|
borderRadius: 5,
|
|
}}
|
|
>
|
|
<Text style={{ fontWeight: "bold", color: "white" }}>
|
|
LIVE
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
)}
|
|
|
|
<View
|
|
style={{
|
|
height: 60,
|
|
width: 2,
|
|
backgroundColor: "hsla(0, 0%, 37%, 1.00)",
|
|
marginHorizontal: 5,
|
|
borderRadius: 5,
|
|
}}
|
|
/>
|
|
|
|
{uniqueStreamingServices.map((serviceName) => {
|
|
const streamingService =
|
|
streamingServices[
|
|
`assets.images.streamingServices.${serviceName.toLowerCase()}`
|
|
];
|
|
return (
|
|
<TouchableOpacity
|
|
key={serviceName}
|
|
style={{
|
|
padding: 5,
|
|
backgroundColor: "hsla(0, 0%, 29%, 1.00)",
|
|
borderRadius: 50,
|
|
borderWidth: serviceName.includes(activeFilter) ? 2 : 0,
|
|
borderColor: "hsla(0, 100%, 50%, 1.00)",
|
|
}}
|
|
onPress={() => handleFilter(serviceName)}
|
|
>
|
|
<Image
|
|
source={{ uri: streamingService }}
|
|
style={{
|
|
width: 50,
|
|
height: 50,
|
|
borderRadius: 30,
|
|
resizeMode: "contain",
|
|
}}
|
|
/>
|
|
</TouchableOpacity>
|
|
);
|
|
})}
|
|
</ScrollView>
|
|
</View>
|
|
<View style={{ flex: 1, paddingHorizontal: 10 }}>
|
|
{filteredShows.map((show) => {
|
|
const showLiveBadge = show.running;
|
|
|
|
return (
|
|
<ShowCard
|
|
key={show.id}
|
|
title={show.title}
|
|
onPress={() =>
|
|
router.push({
|
|
pathname: "/showDetails",
|
|
params: {
|
|
id: String(show.id),
|
|
title: show.title,
|
|
bannerUri: show.bannerUri,
|
|
description: show.description,
|
|
concept: show.concept,
|
|
genres: show.genres,
|
|
streamingService: show.streamingService,
|
|
logoUri: show.logoUrl,
|
|
running: String(show.running),
|
|
},
|
|
})
|
|
}
|
|
imageUri={show.bannerUri}
|
|
streamingServicesUris={show.streamingService
|
|
.split(", ")
|
|
.map(
|
|
(s) =>
|
|
streamingServices[
|
|
`assets.images.streamingServices.${s.toLowerCase()}`
|
|
]
|
|
)}
|
|
genres={show.genres}
|
|
{...(showLiveBadge
|
|
? {
|
|
liveBadgeText: "LIVE",
|
|
liveBadgeContainerStyle: styles.liveBadgeContainer,
|
|
}
|
|
: {})}
|
|
/>
|
|
);
|
|
})}
|
|
</View>
|
|
</ScrollView>
|
|
</View>
|
|
</GestureHandlerRootView>
|
|
);
|
|
}
|