web layout

This commit is contained in:
2025-10-01 13:21:46 +02:00
parent 08e02a752a
commit 7ee47a1943
5 changed files with 89 additions and 54 deletions
+8 -3
View File
@@ -1,9 +1,9 @@
import { View, Text, Pressable, Image, FlatList } from "react-native";
import React from "react"; import React from "react";
import { LinearGradient } from "./LinearGradient/LinearGradient"; import { Image, Pressable, Text } from "react-native";
import { Palette, Style } from "../styles"; import { Palette, Style } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts"; import { FONT_FAMILY } from "../styles/Fonts";
import { size } from "../styles/Style"; import { size } from "../styles/Style";
import { LinearGradient } from "./LinearGradient/LinearGradient";
const GradientButton = ({ const GradientButton = ({
title = "", title = "",
@@ -13,12 +13,17 @@ const GradientButton = ({
containerStyle = {}, containerStyle = {},
icon, icon,
disabled = false, disabled = false,
maxWidth = null,
}) => { }) => {
return ( return (
<Pressable <Pressable
onPress={onPress} onPress={onPress}
disabled={disabled} disabled={disabled}
style={{ ...containerStyle, opacity: disabled ? 0.6 : 1 }} style={{
...containerStyle,
opacity: disabled ? 0.6 : 1,
maxWidth: maxWidth ? maxWidth : null,
}}
> >
<LinearGradient <LinearGradient
colors={colors} colors={colors}
@@ -1,6 +1,6 @@
import React, { useMemo, useState } from "react";
import { FlatList, SectionList, Text, View, Platform } from "react-native";
import { BlurView } from "expo-blur"; import { BlurView } from "expo-blur";
import React, { useMemo, useState } from "react";
import { FlatList, Platform, SectionList, Text, View } from "react-native";
import CreateLyricsHeader from "../../screens/Writing/components/CreateLyricsHeader"; import CreateLyricsHeader from "../../screens/Writing/components/CreateLyricsHeader";
import { Palette } from "../../styles"; import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts"; import { FONT_FAMILY } from "../../styles/Fonts";
@@ -30,7 +30,7 @@ const ListSelection = ({
}) => { }) => {
// Internal fallback state when not provided by parent // Internal fallback state when not provided by parent
const [internalSelected, setInternalSelected] = useState( const [internalSelected, setInternalSelected] = useState(
variant === "sectioned" ? {} : multiple ? [] : null, variant === "sectioned" ? {} : multiple ? [] : null
); );
const selected = selectedProp !== undefined ? selectedProp : internalSelected; const selected = selectedProp !== undefined ? selectedProp : internalSelected;
const setSelected = const setSelected =
@@ -170,11 +170,15 @@ const ListSelection = ({
); );
}} }}
renderSectionHeader={({ section: { title } }) => ( renderSectionHeader={({ section: { title } }) => (
<View style={{ alignSelf: "flex-start", marginLeft: 10, marginBottom: 6 }}> <View
style={{ alignSelf: "flex-start", marginLeft: 10, marginBottom: 6 }}
>
<BlurView <BlurView
intensity={40} intensity={40}
tint="dark" tint="dark"
experimentalBlurMethod={Platform.OS !== "ios" ? "dimezisBlurView" : "none"} experimentalBlurMethod={
Platform.OS !== "ios" ? "dimezisBlurView" : "none"
}
style={{ style={{
borderRadius: 18, borderRadius: 18,
overflow: "hidden", overflow: "hidden",
+3 -6
View File
@@ -1,9 +1,9 @@
import { View, Text, Image, Pressable } from "react-native";
import React from "react"; import React from "react";
import { Image, Pressable, Text, View } from "react-native";
import { icons } from "../assets"; import { icons } from "../assets";
import { Palette, Style } from "../styles"; import { Palette, Style } from "../styles";
import ProgressBar from "./ProgressBar";
import { FONT_FAMILY } from "../styles/Fonts"; import { FONT_FAMILY } from "../styles/Fonts";
import ProgressBar from "./ProgressBar";
const MusicLandHeader = ({ const MusicLandHeader = ({
onPressBack, onPressBack,
@@ -13,10 +13,7 @@ const MusicLandHeader = ({
}) => { }) => {
return ( return (
<View style={{ alignItems: "center", gap: 16 }}> <View style={{ alignItems: "center", gap: 16 }}>
<Image <Image source={icons.musicLandLogo} />
source={icons.musicLandLogo}
/>
<View style={{ width: "100%", ...Style.containerRow, gap: 16 }}> <View style={{ width: "100%", ...Style.containerRow, gap: 16 }}>
<Pressable <Pressable
style={{ width: 24, height: 24, ...Style.containerCenter }} style={{ width: 24, height: 24, ...Style.containerCenter }}
+61 -33
View File
@@ -1,33 +1,36 @@
import { View, Dimensions, Platform } from "react-native";
import React, { useMemo, useRef, useState } from "react"; import React, { useMemo, useRef, useState } from "react";
import Page from "../../layouts/Page"; import { Dimensions, Platform, View } from "react-native";
import MusicLandHeader from "../../components/MusicLandHeader"; import { responsiveHeight } from "react-native-responsive-dimensions";
import GradientButton from "../../components/GradientButton";
import { gutters } from "../../styles";
import { SwiperFlatList } from "react-native-swiper-flatlist"; import { SwiperFlatList } from "react-native-swiper-flatlist";
import Goals from "./Goals"; import { background } from "../../assets";
import { goBack, navigate } from "../../navigation/NavigationService"; import GradientButton from "../../components/GradientButton";
import MusicLandHeader from "../../components/MusicLandHeader";
import useLayoutType from "../../hooks/useLayoutType";
import Page from "../../layouts/Page";
import { Routes } from "../../navigation"; import { Routes } from "../../navigation";
import SpecificityContext from "./SpecificityContext"; import { goBack, navigate } from "../../navigation/NavigationService";
import { useUser } from "../../providers/UserDataProvider";
import { gutters } from "../../styles";
import CreatingLyrics from "./CreatingLyrics";
import CustomizeSongStructure from "./CustomizeSongStructure";
import EmotionConvey from "./EmotionConvey"; import EmotionConvey from "./EmotionConvey";
import Goals from "./Goals";
import Rhymes from "./Rhymes";
import SongStructure from "./SongStructure";
import SongStyle from "./SongStyle"; import SongStyle from "./SongStyle";
import SongTo from "./SongTo"; import SongTo from "./SongTo";
import SongStructure from "./SongStructure"; import SpecificityContext from "./SpecificityContext";
import CustomizeSongStructure from "./CustomizeSongStructure"; const { width: windowWidth } = Dimensions.get("window");
import Rhymes from "./Rhymes";
import CreatingLyrics from "./CreatingLyrics";
import { responsiveHeight } from "react-native-responsive-dimensions";
import { useUser } from "../../providers/UserDataProvider";
const { width } = Dimensions.get("window");
const CreateLyricsWithAi = () => { const CreateLyricsWithAi = () => {
const { isWeb } = useLayoutType();
const { selectedProject, updateProjectData } = useUser(); const { selectedProject, updateProjectData } = useUser();
const hasLyrics = selectedProject?.hasLyrics === true; const hasLyrics = selectedProject?.hasLyrics === true;
const scrollRef = useRef(null); const scrollRef = useRef(null);
const [selectedIndex, setSelectedIndex] = useState(hasLyrics ? 5 : 0); const [selectedIndex, setSelectedIndex] = useState(hasLyrics ? 5 : 0);
const [progress, setProgress] = useState(16); const [progress, setProgress] = useState(16);
const [parentLayout, setparentLayout] = useState(null); const [parentLayout, setparentLayout] = useState(null);
const containerWidth = isWeb ? parentLayout?.width : windowWidth;
// Collected state across steps // Collected state across steps
const [objective, setObjective] = useState(null); // from Goals list const [objective, setObjective] = useState(null); // from Goals list
@@ -162,12 +165,16 @@ const CreateLyricsWithAi = () => {
const isNextDisabled = React.useMemo(() => { const isNextDisabled = React.useMemo(() => {
switch (selectedIndex) { switch (selectedIndex) {
case 0: { case 0: {
const hasObjective = typeof objective === "string" && objective.length > 0; const hasObjective =
const hasOther = typeof otherObjective === "string" && otherObjective.trim().length > 0; typeof objective === "string" && objective.length > 0;
const hasOther =
typeof otherObjective === "string" &&
otherObjective.trim().length > 0;
return !(hasObjective || hasOther); return !(hasObjective || hasOther);
} }
case 1: { case 1: {
const hasContext = typeof context === "string" && context.trim().length > 0; const hasContext =
typeof context === "string" && context.trim().length > 0;
return !hasContext; return !hasContext;
} }
case 2: { case 2: {
@@ -178,15 +185,18 @@ const CreateLyricsWithAi = () => {
} }
case 3: { case 3: {
const hasStyle = typeof style === "string" && style.length > 0; const hasStyle = typeof style === "string" && style.length > 0;
const hasOther = typeof otherStyle === "string" && otherStyle.trim().length > 0; const hasOther =
typeof otherStyle === "string" && otherStyle.trim().length > 0;
return !(hasStyle || hasOther); return !(hasStyle || hasOther);
} }
case 4: { case 4: {
const hasAudience = typeof audience === "string" && audience.trim().length > 0; const hasAudience =
typeof audience === "string" && audience.trim().length > 0;
return !hasAudience; return !hasAudience;
} }
case 5: { case 5: {
const hasStructure = typeof structure === "string" && structure.length > 0; const hasStructure =
typeof structure === "string" && structure.length > 0;
return !hasStructure; return !hasStructure;
} }
case 7: { case 7: {
@@ -196,7 +206,18 @@ const CreateLyricsWithAi = () => {
default: default:
return false; return false;
} }
}, [selectedIndex, objective, otherObjective, context, emotion, style, otherStyle, audience, structure, rhymes]); }, [
selectedIndex,
objective,
otherObjective,
context,
emotion,
style,
otherStyle,
audience,
structure,
rhymes,
]);
const onPressNext = async () => { const onPressNext = async () => {
// Si l'utilisateur a déjà des paroles et vient de finir CustomizeSongStructure (index 6), // Si l'utilisateur a déjà des paroles et vient de finir CustomizeSongStructure (index 6),
@@ -260,6 +281,7 @@ const CreateLyricsWithAi = () => {
headerType="NONE" headerType="NONE"
behavior={Platform.OS === "ios" ? "padding" : "height"} behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 100} keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 100}
backgroundImg={background.homeBG}
> >
<MusicLandHeader onPressBack={onPressBack} progress={progress} /> <MusicLandHeader onPressBack={onPressBack} progress={progress} />
<View <View
@@ -274,14 +296,18 @@ const CreateLyricsWithAi = () => {
onLayout={(e) => setparentLayout(e.nativeEvent.layout)} onLayout={(e) => setparentLayout(e.nativeEvent.layout)}
> >
<SwiperFlatList <SwiperFlatList
style={{ width, left: -gutters }} style={
Platform.OS === "web"
? { width: containerWidth }
: { width: containerWidth, left: -gutters }
}
ref={scrollRef} ref={scrollRef}
disableGesture disableGesture
index={selectedIndex} index={selectedIndex}
> >
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -295,7 +321,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -304,7 +330,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -313,7 +339,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -327,7 +353,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -336,7 +362,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -345,7 +371,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -364,7 +390,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -373,7 +399,7 @@ const CreateLyricsWithAi = () => {
</View> </View>
<View <View
style={{ style={{
width: width, width: containerWidth,
height: parentLayout?.height, height: parentLayout?.height,
paddingHorizontal: gutters, paddingHorizontal: gutters,
}} }}
@@ -400,9 +426,11 @@ const CreateLyricsWithAi = () => {
</View> </View>
{selectedIndex !== 8 && ( {selectedIndex !== 8 && (
<GradientButton <GradientButton
maxWidth={500}
title={selectedIndex === 7 ? "Générer" : "Suivant"} title={selectedIndex === 7 ? "Générer" : "Suivant"}
disabled={isNextDisabled} disabled={isNextDisabled}
onPress={onPressNext} onPress={onPressNext}
containerStyle={{ alignSelf: "center", width: "100%" }}
/> />
)} )}
</View> </View>
+8 -7
View File
@@ -1,12 +1,12 @@
import { View, StyleSheet } from "react-native";
import React, { useState } from "react"; import React, { useState } from "react";
import CreateLyricsHeader from "./components/CreateLyricsHeader"; import { StyleSheet, View } from "react-native";
import { Palette } from "../../styles";
import { GOALS } from "../../data/data";
import { FONT_FAMILY } from "../../styles/Fonts";
import CustomInput from "./components/CustomInput";
import ItemContainer from "../../components/ItemContainer/ItemContainer"; import ItemContainer from "../../components/ItemContainer/ItemContainer";
import ListSelection from "../../components/ListSelection/ListSelection"; import ListSelection from "../../components/ListSelection/ListSelection";
import { GOALS } from "../../data/data";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import CreateLyricsHeader from "./components/CreateLyricsHeader";
import CustomInput from "./components/CustomInput";
const Goals = ({ const Goals = ({
selected: selectedProp, selected: selectedProp,
@@ -24,7 +24,7 @@ const Goals = ({
return ( return (
<View style={{ flex: 1, gap: 16, marginTop: 16 }}> <View style={{ flex: 1, gap: 16, marginTop: 16 }}>
<View style={{ gap: 10 }}> <View style={{ gap: 10 }}>
<CreateLyricsHeader title="Quels est ton objectif ?" /> <CreateLyricsHeader title="Quel est ton objectif ?" />
<ItemContainer> <ItemContainer>
<ListSelection <ListSelection
options={GOALS} options={GOALS}
@@ -56,6 +56,7 @@ const styles = StyleSheet.create({
gap: 10, gap: 10,
backgroundColor: "#FFFFFF00", backgroundColor: "#FFFFFF00",
paddingBottom: 50, paddingBottom: 50,
width: "100%",
}, },
itemContainer: { itemContainer: {
height: 54, height: 54,