add orders collecrtion for coins and subscriptions page

This commit is contained in:
Thomas Demirdjian
2025-11-05 11:18:43 +01:00
parent ffaccd71a7
commit a7371323c4
17 changed files with 1613 additions and 228 deletions
+212 -35
View File
@@ -1,7 +1,16 @@
import React, { useMemo, useState } from "react";
import { Platform, ScrollView, StyleSheet, Text, View } from "react-native";
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 { GOALS, OTHER_OBJECTIVE_OPTION } from "../../data/data";
import { strings } from "../../constants/strings";
import { Palette } from "../../styles";
@@ -15,10 +24,22 @@ const Goals = ({
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 setSelected = setSelectedProp ?? setInternalSelected;
const setSelectedBase = setSelectedProp ?? setInternalSelected;
const trimmedOtherObjective = normalizedOtherObjective.trim();
const hasOtherObjectiveValue = trimmedOtherObjective.length > 0;
const goalsOptions = useMemo(() => GOALS ?? [], []);
@@ -27,47 +48,145 @@ const Goals = ({
const trimmed = value?.trim() ?? "";
if (trimmed.length) {
if (selected !== OTHER_OBJECTIVE_OPTION) {
setSelected(OTHER_OBJECTIVE_OPTION);
setSelectedBase(OTHER_OBJECTIVE_OPTION);
}
} else if (selected === OTHER_OBJECTIVE_OPTION) {
setSelected(null);
setSelectedBase(null);
setPreviousSelection(null);
}
};
// Selection handled by ListSelection
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 }}>
<CreateLyricsHeader
title={strings.writing.steps.contextTitle}
subTitle={strings.writing.steps.contextSubtitle}
/>
<View style={styles.examplesContainer}>
<Text style={styles.examplesText}>
{strings.writing.steps.contextExamples}
</Text>
</View>
<ItemContainer>
<ListSelection
options={goalsOptions}
variant="simple"
selected={selected}
setSelected={setSelected}
contentContainerStyle={styles.contentContainer}
itemContainerStyle={styles.itemContainer}
itemTextStyle={styles.itemText}
<>
<ScrollView contentContainerStyle={{ flex: 1, gap: 16, marginTop: 16 }}>
<View style={{ gap: 10 }}>
<CreateLyricsHeader
title={strings.writing.steps.contextTitle}
subTitle={strings.writing.steps.contextSubtitle}
/>
</ItemContainer>
</View>
<CustomInput
label={strings.writing.labels.otherObjective}
placeholder={strings.writing.labels.otherObjectivePlaceholder}
value={otherObjective}
setValue={handleOtherObjectiveChange}
height={Platform.OS === "web" ? 160 : undefined}
/>
</ScrollView>
<View style={styles.examplesContainer}>
<Text style={styles.examplesText}>
{strings.writing.steps.contextExamples}
</Text>
</View>
<ItemContainer>
<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>
</>
);
};
@@ -112,4 +231,62 @@ const styles = StyleSheet.create({
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,
},
});