This commit is contained in:
Philip Cesar Garay
2025-08-07 21:02:22 +08:00
parent 40e877774b
commit 5a4d36e1bc
34 changed files with 902 additions and 137 deletions
+123
View File
@@ -0,0 +1,123 @@
import { View, Text, Image } from "react-native";
import React, { useState } from "react";
import MusicLandHeader from "../../components/MusicLandHeader";
import { background, icons, img } from "../../assets";
import Page from "../../layouts/Page";
import { goBack, navigate } from "../../navigation/NavigationService";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import { gutters, Palette, Style } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import BorderGradientButton from "../../components/BorderGradientButton";
import GradientButton from "../../components/GradientButton";
import { launchImageLibraryAsync } from "expo-image-picker";
import { Routes } from "../../navigation";
const AddPhotoCover = () => {
const [image, setImage] = useState(null);
const onPressAddImage = async () => {
const result = await launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
setImage(result.assets[0]?.uri);
}
};
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={goBack} progress={90} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader
title="Ta pochette est prête!"
subTitle="Quen penses-tu ?"
/>
<View style={{ flex: 1, ...Style.containerCenter }}>
<View style={{ width: "80%", position: "relative" }}>
<Image
source={img.placeholder}
style={{
width: "100%",
height: 300,
borderRadius: 20,
transform: [{ rotateY: "180deg" }],
}}
/>
<View
style={{ position: "absolute", width: "100%", height: "100%" }}
>
<Image
source={{ uri: image }}
style={{ width: "100%", height: "100%", borderRadius: 20 }}
/>
</View>
<View
style={{
position: "absolute",
alignSelf: "center",
alignItems: "center",
top: 10,
}}
>
<Text
style={{
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
}}
>
Lust for Life
</Text>
<Text
style={{
fontSize: 14,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
Lana del Rey
</Text>
</View>
<View
style={{
position: "absolute",
alignItems: "center",
bottom: 10,
width: "100%",
}}
>
<Image
source={icons.musicLandLogo}
style={{ width: "100%", height: 30 }}
resizeMode="contain"
/>
</View>
</View>
</View>
</View>
<View
style={{
paddingBottom: gutters * 2,
width: "80%",
alignSelf: "center",
gap: 12,
}}
>
<BorderGradientButton
title="Ajouter une autre photo"
onPress={onPressAddImage}
/>
<GradientButton
title="Valider"
onPress={() => navigate(Routes.FinishCompose)}
/>
</View>
</Page>
);
};
export default AddPhotoCover;
+1 -1
View File
@@ -10,7 +10,7 @@ import ItemContainer from "../../components/ItemContainer/ItemContainer";
const ChooseGenre = () => {
return (
<View style={{ flex: 1, gap: 10 }}>
<View style={{ flex: 1, gap: 10, paddingTop: 16 }}>
<CreateLyricsHeader
title="Choisis un genre"
subTitle="Tu peux choisir jusqu’à 2 genres différents"
+5 -4
View File
@@ -5,12 +5,13 @@ import ItemContainer from "../../components/ItemContainer/ItemContainer";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { BlurView } from "expo-blur";
import { INSTRUMENTS } from "../../data/data";
const ChooseInstruments = () => {
const [containerLayout, setContainerLayout] = useState(null);
return (
<View style={{ flex: 1, gap: 10 }}>
<View style={{ flex: 1, gap: 10, paddingTop: 16 }}>
<CreateLyricsHeader
title="Choisis des instruments"
subTitle="Tu peux choisir jusqu’à 5 instruments différents"
@@ -21,10 +22,10 @@ const ChooseInstruments = () => {
>
<ItemContainer height={containerLayout?.height}>
<FlatList
data={Array.from({ length: 10 })}
data={INSTRUMENTS}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.contentContainer}
renderItem={() => (
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<BlurView
intensity={30}
@@ -35,7 +36,7 @@ const ChooseInstruments = () => {
justifyContent: "center",
}}
>
<Text style={styles.itemText}>Piano classique</Text>
<Text style={styles.itemText}>{item}</Text>
</BlurView>
</View>
)}
+5 -4
View File
@@ -5,18 +5,19 @@ import ItemContainer from "../../components/ItemContainer/ItemContainer";
import { BlurView } from "expo-blur";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { RHYTHM } from "../../data/data";
const ChooseRhythm = () => {
return (
<View style={{ flex: 1, gap: 10 }}>
<View style={{ flex: 1, gap: 10, paddingTop: 16 }}>
<CreateLyricsHeader title="Choisis un rythme" />
<View style={{ flex: 1 }}>
<ItemContainer height={340}>
<FlatList
data={Array.from({ length: 5 })}
data={RHYTHM}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.contentContainer}
renderItem={() => (
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<BlurView
intensity={30}
@@ -27,7 +28,7 @@ const ChooseRhythm = () => {
justifyContent: "center",
}}
>
<Text style={styles.itemText}>Très rapide</Text>
<Text style={styles.itemText}>{item}</Text>
</BlurView>
</View>
)}
+1 -1
View File
@@ -12,7 +12,7 @@ const Compose = () => {
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<Image source={ai.theo} style={styles.img} resizeMode="contain" />
<MusicLandHeader showSkip onPressBack={goBack} progress={7.1} />
<MusicLandHeader showSkip onPressBack={goBack} progress={9} />
<View
style={{ flex: 1, position: "relative", justifyContent: "flex-end" }}
>
+4 -6
View File
@@ -19,13 +19,12 @@ const { width } = Dimensions.get("window");
const ComposeSong = () => {
const scrollRef = useRef(null);
const [selectedIndex, setSelectedIndex] = useState(0);
const [progress, setProgress] = useState(14.2);
const [progress, setProgress] = useState(18);
const [containerLayout, setContainerLayout] = useState(null);
console.log("progress: ", progress);
const onPressNext = () => {
setSelectedIndex(selectedIndex + 1);
setProgress(progress + 7.1);
setProgress(progress + 9);
scrollRef.current.scrollToIndex({
index: selectedIndex + 1,
animated: true,
@@ -35,7 +34,7 @@ const ComposeSong = () => {
const onPressBack = () => {
if (selectedIndex > 0) {
setSelectedIndex(selectedIndex - 1);
setProgress(progress - 7.1);
setProgress(progress - 9);
scrollRef.current.scrollToIndex({
index: selectedIndex - 1,
animated: true,
@@ -47,9 +46,8 @@ const ComposeSong = () => {
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<Image source={ai.theo} style={styles.img} resizeMode="contain" />
<MusicLandHeader onPressBack={onPressBack} progress={progress} />
<View style={{ flex: 1, marginTop: 16, paddingBottom: gutters, gap: 48 }}>
<View style={{ flex: 1, paddingBottom: gutters, gap: 48 }}>
<View
style={{ flex: 1 }}
onLayout={(event) => setContainerLayout(event.nativeEvent.layout)}
+5 -3
View File
@@ -6,7 +6,7 @@ import Style, { size } from "../../styles/Style";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import ProgressBar from "../../components/ProgressBar";
import { navigate } from "../../navigation/NavigationService";
import { goBack, navigate } from "../../navigation/NavigationService";
import { Routes } from "../../navigation";
import GradientButton from "../../components/GradientButton";
@@ -19,7 +19,7 @@ const CreatingSong = ({ active }) => {
setProgress((prevProgress) => {
if (prevProgress >= 100) {
clearInterval(interval);
navigate(Routes.SongReady)
return 100;
}
return prevProgress + 1;
@@ -34,6 +34,7 @@ const CreatingSong = ({ active }) => {
<View
style={{
flex: 1,
paddingTop: 16,
...Style.containerCenter,
}}
>
@@ -69,6 +70,7 @@ const CreatingSong = ({ active }) => {
>
<BlurView
intensity={40}
tint="dark"
style={{ flex: 1, padding: 10, paddingBottom: 20 }}
>
<Pressable
@@ -80,7 +82,7 @@ const CreatingSong = ({ active }) => {
left: 10,
zIndex: 3,
}}
onPress={() => console.log("Pressed")}
onPress={goBack}
>
<Image source={icons.close} style={size({ size: 11 })} />
</Pressable>
+6 -6
View File
@@ -5,12 +5,13 @@ import ItemContainer from "../../components/ItemContainer/ItemContainer";
import { Palette, Style } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { BlurView } from "expo-blur";
import { VOICE } from "../../data/data";
const CustomizeVoice = () => {
const [containerLayout, setContainerLayout] = useState(null);
return (
<View style={{ flex: 1, gap: 10 }}>
<View style={{ flex: 1, gap: 10, paddingTop: 16 }}>
<CreateLyricsHeader
title="Personnalise la voix que tu veux pour ta chanson"
subTitle="Choisis maximum 1 option par catégorie."
@@ -33,10 +34,10 @@ const CustomizeVoice = () => {
Base
</Text>
<FlatList
data={Array.from({ length: 10 })}
data={VOICE}
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.contentContainer}
renderItem={() => (
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<BlurView
intensity={30}
@@ -44,10 +45,10 @@ const CustomizeVoice = () => {
flex: 1,
backgroundColor: Palette.glass,
paddingHorizontal: 12,
justifyContent: "center",
paddingVertical: 14,
}}
>
<Text style={styles.itemText}>Une voix féminine interpretra ta chanson.</Text>
<Text style={styles.itemText}>{item}</Text>
</BlurView>
</View>
)}
@@ -70,7 +71,6 @@ const styles = StyleSheet.create({
paddingBottom: 50,
},
itemContainer: {
height: 54,
backgroundColor: Palette.glass,
borderRadius: 14,
overflow: "hidden",
+52
View File
@@ -0,0 +1,52 @@
import { View, Text, Image, StyleSheet } from "react-native";
import React from "react";
import { ai, background } from "../../assets";
import Page from "../../layouts/Page";
import { goBack, navigate } from "../../navigation/NavigationService";
import MusicLandHeader from "../../components/MusicLandHeader";
import { gutters } from "../../styles";
import { Routes } from "../../navigation";
import GradientButton from "../../components/GradientButton";
import BorderGradientButton from "../../components/BorderGradientButton";
const FinishCompose = () => {
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<Image source={ai.theo} style={styles.img} resizeMode="contain" />
<MusicLandHeader onPressBack={goBack} progress={100} />
<View
style={{ flex: 1, position: "relative", justifyContent: "flex-end" }}
>
<View
style={{
paddingBottom: gutters * 2,
width: "70%",
alignSelf: "center",
gap: 12,
}}
>
<BorderGradientButton
title="Continuer plus tard"
onPress={() => navigate(Routes.Onboarding)}
/>
<GradientButton
title="Continuer la création"
onPress={() => navigate(Routes.Onboarding)}
/>
</View>
</View>
</Page>
);
};
export default FinishCompose;
const styles = StyleSheet.create({
img: {
width: "100%",
height: "70%",
position: "absolute",
bottom: -40,
right: -30,
},
});
+93
View File
@@ -0,0 +1,93 @@
import { View, Text, Image } from "react-native";
import React from "react";
import MusicLandHeader from "../../components/MusicLandHeader";
import { background, icons, img } from "../../assets";
import Page from "../../layouts/Page";
import { goBack, navigate } from "../../navigation/NavigationService";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import { gutters, Palette, Style } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import BorderGradientButton from "../../components/BorderGradientButton";
import { Routes } from "../../navigation";
import GradientButton from "../../components/GradientButton";
const PhotoCover = () => {
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={goBack} progress={81} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader title="Souhaites-tu rajouter une photo de toi sur la pochette?" />
<View style={{ flex: 1, ...Style.containerCenter }}>
<View style={{ width: "80%", position: "relative" }}>
<Image
source={img.placeholder}
style={{
width: "100%",
height: 300,
borderRadius: 20,
transform: [{ rotateY: "180deg" }],
}}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
alignItems: "center",
top: 10,
}}
>
<Text
style={{
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
}}
>
Lust for Life
</Text>
<Text
style={{
fontSize: 14,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
Lana del Rey
</Text>
</View>
<View
style={{
position: "absolute",
alignItems: "center",
bottom: 10,
width: "100%",
}}
>
<Image
source={icons.musicLandLogo}
style={{ width: "100%", height: 30 }}
resizeMode="contain"
/>
</View>
</View>
</View>
</View>
<View
style={{
paddingBottom: gutters * 2,
width: "80%",
alignSelf: "center",
gap: 12,
}}
>
<BorderGradientButton title="Non, laisser la pochette telle quelle" />
<GradientButton
title="Oui"
onPress={() => navigate(Routes.AddPhotoCover)}
/>
</View>
</Page>
);
};
export default PhotoCover;
+104
View File
@@ -0,0 +1,104 @@
import { View, Text, Image } from "react-native";
import React from "react";
import Page from "../../layouts/Page";
import { background, icons, img } from "../../assets";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack, navigate } from "../../navigation/NavigationService";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import { gutters, Palette, Style } from "../../styles";
import BorderGradientButton from "../../components/BorderGradientButton";
import GradientButton from "../../components/GradientButton";
import { Routes } from "../../navigation";
import { FONT_FAMILY } from "../../styles/Fonts";
const PouchReady = () => {
return (
<Page backgroundImg={background.studioBG2} headerType="NONE">
<MusicLandHeader onPressBack={goBack} progress={72} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader
title="Ta pochette est prête!"
subTitle="Quen penses-tu ?"
/>
<View style={{ flex: 1, ...Style.containerCenter }}>
<View style={{ width: "80%", position: "relative" }}>
<Image
source={img.placeholder}
style={{
width: "100%",
height: 300,
borderRadius: 20,
transform: [{ rotateY: "180deg" }],
}}
/>
<View
style={{
position: "absolute",
alignSelf: "center",
alignItems: "center",
top: 10,
}}
>
<Text
style={{
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
}}
>
Lust for Life
</Text>
<Text
style={{
fontSize: 14,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
Lana del Rey
</Text>
</View>
<View
style={{
position: "absolute",
alignItems: "center",
bottom: 10,
width: "100%",
}}
>
<Image
source={icons.musicLandLogo}
style={{ width: "100%", height: 30 }}
resizeMode="contain"
/>
</View>
</View>
</View>
</View>
<View
style={{
paddingBottom: gutters * 2,
width: "80%",
alignSelf: "center",
gap: 12,
}}
>
<BorderGradientButton
title="Regénérer"
icon={icons.stars}
onPress={() =>
navigate(Routes.Regenerate, {
progress: 72,
})
}
/>
<GradientButton
title="Valider"
onPress={() => navigate(Routes.PhotoCover)}
/>
</View>
</Page>
);
};
export default PouchReady;
+74
View File
@@ -0,0 +1,74 @@
import { View, Text } from "react-native";
import React from "react";
import Page from "../../layouts/Page";
import { background, icons } from "../../assets";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack } from "../../navigation/NavigationService";
import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import GradientButton from "../../components/GradientButton";
import { useRoute } from "@react-navigation/core";
const Regenerate = () => {
const params = useRoute().params;
return (
<Page
backgroundImg={background.studioBG2}
headerType="NONE"
containerStyle={{ paddingBottom: gutters * 2 }}
>
<MusicLandHeader onPressBack={goBack} progress={params?.progress} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader
title="Regénérer"
subTitle="Veux-tu changer tes choix ?"
/>
<View style={{ gap: 27, marginTop: 30 }}>
<CreateLyricsHeader title="Genre">
<Text
style={{
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
<Text style={{ fontFamily: FONT_FAMILY.InterBold }}>
Hip Hop/Rap
</Text>{" "}
: Musique commerciale destinée au grand public, accrocheuse et
mélodique. Domine les charts internationaux avec des artistes
ultra-médiatisés.
</Text>
</CreateLyricsHeader>
<CreateLyricsHeader
title="Voix"
subTitle="Une voix masculine interpretera ta chanson."
/>
<CreateLyricsHeader title="Instruments">
<Text
style={{
fontSize: 16,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
Banjo{"\n"}Violon{"\n"}
Saxophone{"\n"}
Piano classique{"\n"}
</Text>
</CreateLyricsHeader>
</View>
</View>
<GradientButton
title="Regénérer"
containerStyle={{ width: "80%", alignSelf: "center" }}
icon={icons.stars}
onPress={goBack}
/>
</Page>
);
};
export default Regenerate;
+73 -30
View File
@@ -1,45 +1,88 @@
import { View, Text } from "react-native";
import React from "react";
import React, { useState } from "react";
import Page from "../../layouts/Page";
import { background } from "../../assets";
import { background, icons } from "../../assets";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack } from "../../navigation/NavigationService";
import { LinearGradient } from "../../components/LinearGradient/LinearGradient";
import { goBack, navigate } from "../../navigation/NavigationService";
import Slider from "../../components/Slider";
import { Image, Pressable, View } from "react-native";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import { BlurView } from "expo-blur";
import { Style } from "../../styles";
import { responsiveWidth } from "react-native-responsive-dimensions";
import { gutters, size } from "../../styles/Style";
import BorderGradientButton from "../../components/BorderGradientButton";
import GradientButton from "../../components/GradientButton";
import { Routes } from "../../navigation";
import ValidateModal from "../../components/modal/ValidateModal";
const SongReady = () => {
const [showValidateModal, setShowValidateModal] = useState(false);
return (
<Page headerType="NONE" backgroundImg={background.studioBG2}>
<MusicLandHeader onPressBack={goBack} progress={49.7} />
<View>
<LinearGradient
colors={["#FF0000", "#FFFF00", "#0000FF"]} // Red to Yellow to Blue gradient
start={{ x: 0, y: 0.5 }}
end={{ x: 1, y: 0.5 }}
<MusicLandHeader onPressBack={goBack} progress={63} />
<View style={{ flex: 1, marginTop: 16 }}>
<CreateLyricsHeader
title="Ta chanson est prête !"
subTitle="Quen penses-tu ?"
/>
<View
style={{
width: "100%",
height: 40,
borderRadius: 20, // Optional: for rounded corners
...size({ size: responsiveWidth(80) }),
alignSelf: "center",
borderRadius: 1000,
overflow: "hidden",
marginTop: 16,
}}
>
<Slider
style={{ height: 40, width: "100%" }}
minimumValue={0}
maximumValue={100}
minimumTrackTintColor="transparent"
maximumTrackTintColor="red"
thumbTintColor="#FFFFFF"
/>
</LinearGradient>
<Slider
minimumValue={0}
maximumValue={100}
minimumTrackTintColor="transparent"
maximumTrackTintColor="red"
thumbTintColor="#FFFFFF"
<BlurView
intensity={40}
tint="dark"
style={{ ...Style.containerCenter, flex: 1 }}
>
<Image source={icons.disk} />
</BlurView>
</View>
<View style={{ marginTop: 49 }}>
<Slider value="0" maxValue="2:11" />
<Pressable
style={{
alignSelf: "center",
...size({ size: 48 }),
...Style.containerCenter,
}}
>
<Image source={icons.play} />
</Pressable>
</View>
</View>
<View
style={{
paddingBottom: gutters * 2,
width: "80%",
alignSelf: "center",
gap: 12,
}}
>
<BorderGradientButton
title="Regénérer"
icon={icons.stars}
onPress={() =>
navigate(Routes.Regenerate, {
progress: 63,
})
}
/>
<GradientButton
title="Valider"
onPress={() => setShowValidateModal(true)}
/>
</View>
<ValidateModal
visible={showValidateModal}
onClose={() => setShowValidateModal(false)}
onPressValidate={() => navigate(Routes.PouchReady)}
/>
</Page>
);
};