Files
fltr-app/components/ui/ShowCard.tsx
2026-03-11 13:43:06 +11:00

158 lines
3.5 KiB
TypeScript

import React from "react";
import { Image, StyleSheet, Text, TouchableOpacity, View } from "react-native";
type ShowCardProps = {
imageUri: string;
streamingServicesUris: string[];
liveBadgeText?: string;
genres: string[];
title: string;
onPress?: () => void;
};
const ShowCard = ({
imageUri,
streamingServicesUris,
liveBadgeText,
genres,
onPress,
title,
}: ShowCardProps) => {
return (
<TouchableOpacity style={styles.card} activeOpacity={0.8} onPress={onPress}>
<Image
source={{ uri: imageUri }}
style={[StyleSheet.absoluteFillObject, { borderRadius: 18 }]}
/>
{/* Gradient-like overlay at bottom */}
<View style={styles.bottomGradient} />
{/* Streaming service icons */}
<View style={styles.serviceRow}>
{streamingServicesUris.length > 0 &&
streamingServicesUris.map((service) => (
<Image
key={service}
source={{ uri: service }}
style={styles.serviceIcon}
/>
))}
</View>
{/* Live badge */}
{liveBadgeText && (
<View style={styles.liveBadge}>
<View style={styles.liveDot} />
<Text style={styles.liveBadgeText}>{liveBadgeText}</Text>
</View>
)}
{/* Bottom info */}
<View style={styles.bottomInfo}>
<Text style={styles.title} numberOfLines={1}>
{title}
</Text>
{genres.length > 0 && (
<View style={styles.genreRow}>
{genres.slice(0, 3).map((genre) => (
<Text key={genre} style={styles.genreTag}>
{genre}
</Text>
))}
</View>
)}
</View>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
card: {
width: "100%",
height: 200,
borderRadius: 18,
marginTop: 14,
overflow: "hidden",
backgroundColor: "rgba(255,255,255,0.06)",
},
bottomGradient: {
...StyleSheet.absoluteFillObject,
borderRadius: 18,
backgroundColor: "transparent",
// A dark gradient from bottom for readability
// Using a semi-transparent overlay at bottom
},
serviceRow: {
flexDirection: "row",
justifyContent: "flex-end",
padding: 10,
gap: 6,
},
serviceIcon: {
height: 34,
width: 34,
borderRadius: 17,
resizeMode: "contain",
backgroundColor: "rgba(0,0,0,0.3)",
},
liveBadge: {
position: "absolute",
top: 12,
left: 12,
flexDirection: "row",
alignItems: "center",
gap: 5,
backgroundColor: "rgba(0,0,0,0.55)",
paddingVertical: 4,
paddingHorizontal: 10,
borderRadius: 12,
},
liveDot: {
width: 7,
height: 7,
borderRadius: 4,
backgroundColor: "#ff3b30",
},
liveBadgeText: {
color: "white",
fontWeight: "700",
fontSize: 11,
letterSpacing: 0.5,
},
bottomInfo: {
position: "absolute",
bottom: 0,
left: 0,
right: 0,
paddingHorizontal: 14,
paddingBottom: 12,
paddingTop: 24,
backgroundColor: "rgba(0,0,0,0.45)",
},
title: {
color: "white",
fontWeight: "700",
fontSize: 16,
letterSpacing: 0.2,
},
genreRow: {
flexDirection: "row",
gap: 6,
marginTop: 5,
flexWrap: "wrap",
},
genreTag: {
color: "rgba(255,255,255,0.8)",
fontSize: 11,
fontWeight: "500",
paddingVertical: 2,
paddingHorizontal: 8,
borderRadius: 8,
backgroundColor: "rgba(255,255,255,0.15)",
overflow: "hidden",
},
});
export default ShowCard;