hit parade web
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ const PouchReady = () => {
|
|||||||
height: 300,
|
height: 300,
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
backgroundColor: "#00000040",
|
backgroundColor: "#00000040",
|
||||||
|
alignSelf: "center",
|
||||||
...Style.containerCenter,
|
...Style.containerCenter,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user