Files
musicland/src/screens/Writing/Goals.js
T
2025-11-05 11:37:16 +01:00

290 lines
8.2 KiB
JavaScript

import React, { useMemo, useState } from "react";
import {
Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
View,
} from "react-native";
import { BaseButton } from "../../components/Button";
import ItemContainer from "../../components/ItemContainer/ItemContainer";
import ListSelection from "../../components/ListSelection/ListSelection";
import Overlay from "../../components/Overlay";
import { strings } from "../../constants/strings";
import { GOALS, OTHER_OBJECTIVE_OPTION } 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 = ({
selected: selectedProp,
setSelected: setSelectedProp,
otherObjective,
setOtherObjective,
}) => {
const normalizedOtherObjective =
typeof otherObjective === "string" ? otherObjective : "";
const [internalSelected, setInternalSelected] = useState(null);
const [otherObjectiveModalVisible, setOtherObjectiveModalVisible] =
useState(false);
const [previousSelection, setPreviousSelection] = useState(null);
const [previousOtherObjective, setPreviousOtherObjective] = useState(
normalizedOtherObjective
);
const selected = selectedProp ?? internalSelected;
const setSelectedBase = setSelectedProp ?? setInternalSelected;
const trimmedOtherObjective = normalizedOtherObjective.trim();
const hasOtherObjectiveValue = trimmedOtherObjective.length > 0;
const goalsOptions = useMemo(() => GOALS ?? [], []);
const handleOtherObjectiveChange = (value) => {
setOtherObjective?.(value);
const trimmed = value?.trim() ?? "";
if (trimmed.length) {
if (selected !== OTHER_OBJECTIVE_OPTION) {
setSelectedBase(OTHER_OBJECTIVE_OPTION);
}
} else if (selected === OTHER_OBJECTIVE_OPTION) {
setSelectedBase(null);
setPreviousSelection(null);
}
};
const handleGoalSelect = (value) => {
if (value === OTHER_OBJECTIVE_OPTION) {
setPreviousSelection(selected ?? null);
setPreviousOtherObjective(normalizedOtherObjective);
setSelectedBase(value);
setOtherObjectiveModalVisible(true);
return;
}
setSelectedBase(value);
setOtherObjectiveModalVisible(false);
setPreviousSelection(null);
};
const handleOpenOtherObjectiveModal = () => {
setPreviousSelection(selected ?? null);
setPreviousOtherObjective(normalizedOtherObjective);
setOtherObjectiveModalVisible(true);
};
const handleCancelOtherObjective = () => {
setOtherObjectiveModalVisible(false);
setOtherObjective?.(previousOtherObjective);
if (selected === OTHER_OBJECTIVE_OPTION) {
setSelectedBase(previousSelection ?? null);
}
setPreviousSelection(null);
};
const handleConfirmOtherObjective = () => {
if (!hasOtherObjectiveValue) {
const fallback =
previousSelection && previousSelection !== OTHER_OBJECTIVE_OPTION
? previousSelection
: null;
setOtherObjective?.(previousOtherObjective);
setSelectedBase(fallback);
setOtherObjectiveModalVisible(false);
setPreviousSelection(null);
return;
}
if (selected !== OTHER_OBJECTIVE_OPTION) {
setSelectedBase(OTHER_OBJECTIVE_OPTION);
}
setOtherObjectiveModalVisible(false);
setPreviousSelection(OTHER_OBJECTIVE_OPTION);
};
return (
<>
<ScrollView contentContainerStyle={{ flex: 1, gap: 16, marginTop: 16 }}>
<View style={{ gap: 10, height: "100%" }}>
<CreateLyricsHeader title={strings.writing.steps.contextTitle} />
{/* <View style={styles.examplesContainer}>
<Text style={styles.examplesText}>
{strings.writing.steps.contextExamples}
</Text>
</View> */}
<ItemContainer height={"80%"}>
<ListSelection
options={goalsOptions}
variant="simple"
selected={selected}
setSelected={handleGoalSelect}
contentContainerStyle={styles.contentContainer}
itemContainerStyle={styles.itemContainer}
itemTextStyle={styles.itemText}
/>
</ItemContainer>
</View>
{selected === OTHER_OBJECTIVE_OPTION ? (
<View style={styles.otherObjectiveSummary}>
<View style={{ flex: 1, gap: 4 }}>
<Text style={styles.summaryLabel}>
{strings.writing.labels.otherObjective}
</Text>
<Text
style={[
styles.summaryValue,
!hasOtherObjectiveValue && styles.summaryPlaceholder,
]}
numberOfLines={3}
>
{hasOtherObjectiveValue
? trimmedOtherObjective
: strings.writing.labels.otherObjectivePlaceholder}
</Text>
</View>
<Pressable
style={styles.summaryButton}
onPress={handleOpenOtherObjectiveModal}
>
<Text style={styles.summaryButtonText}>
{hasOtherObjectiveValue ? "Modifier" : "Ajouter"}
</Text>
</Pressable>
</View>
) : null}
</ScrollView>
<Overlay
isVisible={otherObjectiveModalVisible}
setIsVisible={handleCancelOtherObjective}
>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>
{strings.writing.labels.otherObjective}
</Text>
<CustomInput
placeholder={strings.writing.labels.otherObjectivePlaceholder}
value={otherObjective}
setValue={handleOtherObjectiveChange}
height={Platform.OS === "web" ? 160 : undefined}
/>
<View style={styles.modalActions}>
<BaseButton
type="secondary"
text="Annuler"
onPress={handleCancelOtherObjective}
containerStyle={styles.modalActionButton}
/>
<BaseButton
text="Valider"
onPress={handleConfirmOtherObjective}
containerStyle={styles.modalActionButton}
/>
</View>
</View>
</Overlay>
</>
);
};
export default Goals;
const styles = StyleSheet.create({
contentContainer: {
flexGrow: 1,
padding: 8,
gap: 10,
backgroundColor: "#FFFFFF00",
paddingBottom: 50,
width: "100%",
},
itemContainer: {
height: 54,
borderRadius: 14,
shadowColor: "#00000040",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
itemText: {
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
textAlign: "center",
},
examplesContainer: {
backgroundColor: Palette.ultraLightWhite,
borderRadius: 12,
padding: 12,
},
examplesText: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
lineHeight: 20,
},
otherObjectiveSummary: {
backgroundColor: Palette.ultraLightWhite,
borderRadius: 12,
padding: 12,
flexDirection: "row",
alignItems: "flex-start",
gap: 12,
},
summaryLabel: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
summaryValue: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
lineHeight: 20,
},
summaryPlaceholder: {
color: Palette.grayMid,
fontStyle: "italic",
},
summaryButton: {
alignSelf: "flex-start",
paddingVertical: 6,
paddingHorizontal: 12,
borderRadius: 999,
borderWidth: 1,
borderColor: Palette.white,
backgroundColor: "#FFFFFF10",
},
summaryButtonText: {
fontSize: 12,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
modalContent: {
width: "90%",
maxWidth: 420,
padding: 20,
borderRadius: 16,
backgroundColor: Palette.darkPurple,
gap: 16,
},
modalTitle: {
fontSize: 18,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
textAlign: "center",
},
modalActions: {
flexDirection: "row",
gap: 12,
},
modalActionButton: {
flex: 1,
},
});