hit parade web

This commit is contained in:
2025-10-02 15:58:34 +02:00
parent ffbf428974
commit e566052766
2 changed files with 164 additions and 62 deletions
+163 -62
View File
@@ -1,5 +1,13 @@
import React, { useState } from "react"; import React, { useMemo, useState } from "react";
import { FlatList, Image, Pressable, Text, View } from "react-native"; import {
FlatList,
Image,
Platform,
Pressable,
ScrollView,
Text,
View,
} from "react-native";
import { responsiveHeight } from "react-native-responsive-dimensions"; import { responsiveHeight } from "react-native-responsive-dimensions";
import { background, icons } from "../../assets"; import { background, icons } from "../../assets";
import BorderGradientButton from "../../components/BorderGradientButton"; import BorderGradientButton from "../../components/BorderGradientButton";
@@ -16,12 +24,14 @@ import SongCard from "./components/SongCard";
const HitParade = () => { const HitParade = () => {
const [selected, setSelected] = useState("Chansons"); const [selected, setSelected] = useState("Chansons");
const { data: topSongs } = useDataFromRef({ const { data: topSongs } = useDataFromRef({
ref: projectsRef.where("views", ">", 0).orderBy("views", "desc").limit(10), ref: projectsRef.where("views", ">", 0).orderBy("views", "desc").limit(10),
simpleRef: false, simpleRef: false,
listener: true, listener: true,
condition: true, condition: true,
}); });
const { data: topPlaybacks } = useDataFromRef({ const { data: topPlaybacks } = useDataFromRef({
ref: projectsRef.where("views", ">", 0).orderBy("views", "desc").limit(50), ref: projectsRef.where("views", ">", 0).orderBy("views", "desc").limit(50),
format: (docs) => docs.filter((d) => d?.playbackUrl != null).slice(0, 10), format: (docs) => docs.filter((d) => d?.playbackUrl != null).slice(0, 10),
@@ -30,6 +40,148 @@ const HitParade = () => {
condition: true, condition: true,
}); });
// Découpe en 2 colonnes (pour le web uniquement)
const [songsCol1, songsCol2] = useMemo(() => {
const arr = Array.isArray(topSongs) ? topSongs : [];
return [arr.slice(0, 5), arr.slice(5)];
}, [topSongs]);
const [playbacksCol1, playbacksCol2] = useMemo(() => {
const arr = Array.isArray(topPlaybacks) ? topPlaybacks : [];
return [arr.slice(0, 5), arr.slice(5)];
}, [topPlaybacks]);
// === RENDUS PAR PLATEFORME ===
const renderSongsMobile = () => (
<FlatList
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
data={Array.isArray(topSongs) ? topSongs : []}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<SongCard
rank={index + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() => navigate(Routes.MusicDetails, { projectId: item.id })}
/>
)}
/>
);
const renderPlaybacksMobile = () => (
<FlatList
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
data={Array.isArray(topPlaybacks) ? topPlaybacks : []}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<PlaybacksCard
rank={index + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() => navigate(Routes.Playbacks, { projectId: item.id })}
/>
)}
/>
);
const renderSongsWeb = () => (
<ScrollView
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
>
<View style={{ flexDirection: "row", gap: 10, alignItems: "flex-start" }}>
{/* Colonne gauche (1..5) */}
<View style={{ flex: 1, gap: 10 }}>
{songsCol1.map((item, idx) => (
<SongCard
key={item.id}
rank={idx + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() =>
navigate(Routes.MusicDetails, { projectId: item.id })
}
/>
))}
</View>
{/* Colonne droite (6..N) */}
{songsCol2.length > 0 && (
<View style={{ flex: 1, gap: 10 }}>
{songsCol2.map((item, idx) => (
<SongCard
key={item.id}
rank={5 + idx + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() =>
navigate(Routes.MusicDetails, { projectId: item.id })
}
/>
))}
</View>
)}
</View>
</ScrollView>
);
const renderPlaybacksWeb = () => (
<ScrollView
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
>
<View style={{ flexDirection: "row", gap: 10, alignItems: "flex-start" }}>
{/* Colonne gauche (1..5) */}
<View style={{ flex: 1, gap: 10 }}>
{playbacksCol1.map((item, idx) => (
<PlaybacksCard
key={item.id}
rank={idx + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() => navigate(Routes.Playbacks, { projectId: item.id })}
/>
))}
</View>
{/* Colonne droite (6..N) */}
{playbacksCol2.length > 0 && (
<View style={{ flex: 1, gap: 10 }}>
{playbacksCol2.map((item, idx) => (
<PlaybacksCard
key={item.id}
rank={5 + idx + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() =>
navigate(Routes.Playbacks, { projectId: item.id })
}
/>
))}
</View>
)}
</View>
</ScrollView>
);
const isWeb = Platform.OS === "web";
return ( return (
<Page backgroundImg={background.hitParadeBG} headerType="NONE"> <Page backgroundImg={background.hitParadeBG} headerType="NONE">
<View style={{ gap: 12, flex: 1 }}> <View style={{ gap: 12, flex: 1 }}>
@@ -44,9 +196,7 @@ const HitParade = () => {
style={{ alignSelf: "center" }} style={{ alignSelf: "center" }}
/> />
<CreateLyricsHeader <CreateLyricsHeader
gradientProps={{ gradientProps={{ colors: ["#F94697", "#7023F7"] }}
colors: ["#F94697", "#7023F7"],
}}
> >
<Text <Text
style={{ style={{
@@ -69,24 +219,21 @@ const HitParade = () => {
</Text> </Text>
</CreateLyricsHeader> </CreateLyricsHeader>
</View> </View>
<View <View
style={{ style={{
...Style.containerRow, ...Style.containerRow,
justifyContent: "space-between", justifyContent: "space-between",
// gap: "5%",
width: "auto", width: "auto",
}} }}
> >
{/*{["Chansons", "Playbacks", "Clips"].map((item, index) => (*/}
{["Chansons", "Playbacks"].map((item, index) => ( {["Chansons", "Playbacks"].map((item, index) => (
<BorderGradientButton <BorderGradientButton
key={index} key={index}
title={item} title={item}
onPress={() => setSelected(item)} onPress={() => setSelected(item)}
tint={selected === item ? "light" : "dark"} tint={selected === item ? "light" : "dark"}
containerStyle={{ containerStyle={{ flex: 1 }}
width: "47%",
}}
titleStyle={{ titleStyle={{
fontSize: 16, fontSize: 16,
fontFamily: FONT_FAMILY.HelveticaNeueBold, fontFamily: FONT_FAMILY.HelveticaNeueBold,
@@ -94,58 +241,12 @@ const HitParade = () => {
/> />
))} ))}
</View> </View>
{selected === "Chansons" && (
<FlatList {selected === "Chansons" &&
contentContainerStyle={{ (isWeb ? renderSongsWeb() : renderSongsMobile())}
gap: 10, {selected === "Playbacks" &&
paddingBottom: responsiveHeight(20), (isWeb ? renderPlaybacksWeb() : renderPlaybacksMobile())}
}} {/* "Clips" pourra reprendre la même logique si tu le réactives */}
data={Array.isArray(topSongs) ? topSongs : []}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<SongCard
rank={index + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() =>
navigate(Routes.MusicDetails, { projectId: item.id })
}
/>
)}
/>
)}
{selected === "Playbacks" && (
<FlatList
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
data={Array.isArray(topPlaybacks) ? topPlaybacks : []}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<PlaybacksCard
rank={index + 1}
title={item?.title || "Sans titre"}
artist={"MusicLand"}
coverUrl={item?.coverUrl || null}
onPress={() =>
navigate(Routes.Playbacks, { projectId: item.id })
}
/>
)}
/>
)}
{selected === "Clips" && (
<FlatList
contentContainerStyle={{
gap: 10,
paddingBottom: responsiveHeight(20),
}}
data={Array.from({ length: 5 })}
renderItem={() => <PlaybacksCard />}
/>
)}
</View> </View>
</View> </View>
</Page> </Page>
+1
View File
@@ -109,6 +109,7 @@ const PouchReady = () => {
height: 300, height: 300,
borderRadius: 20, borderRadius: 20,
backgroundColor: "#00000040", backgroundColor: "#00000040",
alignSelf: "center",
...Style.containerCenter, ...Style.containerCenter,
}} }}
> >