continue generating flow, add backend connection on main tabs
This commit is contained in:
@@ -13,9 +13,10 @@ const BorderGradientButton = ({
|
||||
titleStyle,
|
||||
containerStyle = {},
|
||||
tint = "dark",
|
||||
disabled = false,
|
||||
}) => {
|
||||
return (
|
||||
<Pressable onPress={onPress} style={{ ...containerStyle }}>
|
||||
<Pressable onPress={onPress} disabled={disabled} style={{ ...containerStyle, opacity: disabled ? 0.6 : 1 }}>
|
||||
<BorderGradient
|
||||
gradientProps={{
|
||||
colors: ["#F94697", "#7023F7"],
|
||||
|
||||
+41
-11
@@ -3,6 +3,7 @@ import { View, Text, Image, Pressable, StyleSheet } from "react-native";
|
||||
import { BlurView } from "expo-blur";
|
||||
|
||||
import Switch from "../components/Switch";
|
||||
import OptionSelector from "../components/OptionSelector";
|
||||
import { Container, Title, Input, Button } from "../components/Dialog";
|
||||
|
||||
import { Fonts, Style, gutters } from "../styles";
|
||||
@@ -12,6 +13,15 @@ const labelOptions = {
|
||||
name: "Nouveau nom",
|
||||
email: "Nouvelle adresse email",
|
||||
password: "Nouveau mot de passe",
|
||||
language: "Nouvelle langue",
|
||||
};
|
||||
|
||||
const languageOptions = {
|
||||
fr: "Français",
|
||||
en: "English",
|
||||
es: "Español",
|
||||
de: "Deutsch",
|
||||
it: "Italiano",
|
||||
};
|
||||
|
||||
export default ({ itemKey, type, value, title, onUpdateValue }) => {
|
||||
@@ -51,7 +61,11 @@ export default ({ itemKey, type, value, title, onUpdateValue }) => {
|
||||
},
|
||||
})}
|
||||
>
|
||||
{itemKey === "password" ? "********" : value}
|
||||
{itemKey === "password"
|
||||
? "********"
|
||||
: itemKey === "language"
|
||||
? languageOptions[value] || value
|
||||
: value}
|
||||
</Text>
|
||||
|
||||
<Image
|
||||
@@ -84,20 +98,36 @@ export default ({ itemKey, type, value, title, onUpdateValue }) => {
|
||||
value={currentPassword}
|
||||
onChangeText={(text) => setCurrentPassword(text)}
|
||||
keyboardType="visible-password"
|
||||
type={"password"}
|
||||
containerStyle={{ marginBottom: gutters / 2 }}
|
||||
/>
|
||||
)}
|
||||
{itemKey === "language" ? (
|
||||
<OptionSelector
|
||||
optionTypeList={languageOptions}
|
||||
selected={inputData || "fr"}
|
||||
setSelected={setInputData}
|
||||
containerStyle={{ marginBottom: gutters / 2 }}
|
||||
colorMap={{
|
||||
fr: { primary: "#F94697", secondary: "#F946971A" },
|
||||
en: { primary: "#7023F7", secondary: "#7023F71A" },
|
||||
es: { primary: "#FDBA74", secondary: "#FDBA741A" },
|
||||
de: { primary: "#60A5FA", secondary: "#60A5FA1A" },
|
||||
it: { primary: "#34D399", secondary: "#34D3991A" },
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
label={labelOptions[itemKey]}
|
||||
value={inputData}
|
||||
onChangeText={(text) => setInputData(text)}
|
||||
autoCapitalize={
|
||||
["password", "email"].includes(itemKey) ? "none" : "words"
|
||||
}
|
||||
type={itemKey}
|
||||
containerStyle={{ marginBottom: gutters / 2 }}
|
||||
/>
|
||||
)}
|
||||
<Input
|
||||
label={labelOptions[itemKey]}
|
||||
value={inputData}
|
||||
onChangeText={(text) => setInputData(text)}
|
||||
autoCapitalize={
|
||||
["password", "email"].includes(itemKey) ? "none" : "words"
|
||||
}
|
||||
type={itemKey}
|
||||
containerStyle={{ marginBottom: gutters / 2 }}
|
||||
/>
|
||||
<Button
|
||||
label="Valider"
|
||||
onPress={() => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { FONT_FAMILY } from "../styles/Fonts";
|
||||
|
||||
const INITIAL_BOX_SIZE = 6;
|
||||
|
||||
export default ({ value, maxValue, progress, onSeek, seekEnabled = false }) => {
|
||||
export default ({ value, maxValue, progress, onSeek, onSeekStart, onSeekEnd, seekEnabled = false }) => {
|
||||
const offset = useSharedValue(0);
|
||||
const boxWidth = useSharedValue(INITIAL_BOX_SIZE);
|
||||
const [layout, setLayout] = useState(null);
|
||||
@@ -22,6 +22,12 @@ export default ({ value, maxValue, progress, onSeek, seekEnabled = false }) => {
|
||||
|
||||
const pan = Gesture.Pan()
|
||||
.enabled(seekEnabled)
|
||||
.onBegin(() => {
|
||||
if (seekEnabled && typeof onSeekStart === 'function') {
|
||||
// Notify JS thread that user started seeking (e.g., pause audio)
|
||||
runOnJS(onSeekStart)();
|
||||
}
|
||||
})
|
||||
.onChange((event) => {
|
||||
offset.value =
|
||||
Math.abs(offset.value) <= MAX_VALUE
|
||||
@@ -40,6 +46,11 @@ export default ({ value, maxValue, progress, onSeek, seekEnabled = false }) => {
|
||||
const ratio = MAX_VALUE > 0 ? Math.min(1, Math.max(0, offset.value / MAX_VALUE)) : 0;
|
||||
// Reanimated -> JS thread bridge
|
||||
runOnJS(onSeek)(ratio);
|
||||
})
|
||||
.onFinalize(() => {
|
||||
if (seekEnabled && typeof onSeekEnd === 'function') {
|
||||
runOnJS(onSeekEnd)();
|
||||
}
|
||||
});
|
||||
|
||||
// Reflect external progress into the slider UI
|
||||
|
||||
@@ -1,17 +1,68 @@
|
||||
import { View, Text } from "react-native";
|
||||
import React from "react";
|
||||
import React, { useGlobal } from "reactn";
|
||||
import AppActionSheet from "../AppActionSheet";
|
||||
import BorderGradientButton from "../BorderGradientButton";
|
||||
import GradientButton from "../GradientButton";
|
||||
import { Palette } from "../../styles";
|
||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||
import { SheetManager } from "react-native-actions-sheet";
|
||||
import alert from "../Alert";
|
||||
import firebase, { usersRef } from "../../config/firebase";
|
||||
import { reset } from "../../navigation/NavigationService";
|
||||
import { Routes } from "../../navigation";
|
||||
|
||||
const DeleteAccountModal = () => {
|
||||
const [currentUID] = useGlobal("currentUID");
|
||||
const [, setTooltip] = useGlobal("_tooltip");
|
||||
|
||||
const onClose = async () => {
|
||||
await SheetManager.hide("DeleteAccount");
|
||||
};
|
||||
|
||||
const confirmDelete = () => {
|
||||
alert(
|
||||
"Êtes-vous sûr ?",
|
||||
"Cette action supprimera votre profil.",
|
||||
[
|
||||
{ text: "Annuler", style: "cancel", onPress: () => {} },
|
||||
{
|
||||
text: "Confirmer",
|
||||
onPress: () => {
|
||||
alert(
|
||||
"Confirmation",
|
||||
"Dernière vérification: supprimer définitivement votre profil ?",
|
||||
[
|
||||
{ text: "Non", style: "cancel", onPress: () => {} },
|
||||
{
|
||||
text: "Oui, supprimer",
|
||||
onPress: async () => {
|
||||
try {
|
||||
if (!currentUID) return;
|
||||
await usersRef.doc(currentUID).delete();
|
||||
// Sign out and reset navigation to Login
|
||||
await firebase.auth().signOut();
|
||||
reset({ index: 0, routes: [{ name: Routes.Login }] });
|
||||
setTooltip({ type: "success", text: "Profil supprimé" });
|
||||
} catch (e) {
|
||||
setTooltip({
|
||||
type: "error",
|
||||
text: e?.message || "Suppression impossible",
|
||||
});
|
||||
} finally {
|
||||
onClose();
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
{ cancelable: true },
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
{ cancelable: true },
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AppActionSheet id="DeleteAccount">
|
||||
<View style={{ gap: 20 }}>
|
||||
@@ -39,7 +90,7 @@ const DeleteAccountModal = () => {
|
||||
</Text>
|
||||
</View>
|
||||
<View style={{ width: "80%", alignSelf: "center", gap: 12 }}>
|
||||
<BorderGradientButton title="Oui, supprimer" onPress={onClose} />
|
||||
<BorderGradientButton title="Oui, supprimer" onPress={confirmDelete} />
|
||||
<GradientButton title="Non, annuler" onPress={onClose} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user