From 31e81ef83d2eaf5a83f1ba14c405a978dc880a0b Mon Sep 17 00:00:00 2001 From: leon-morival Date: Sun, 12 Oct 2025 13:47:37 +0200 Subject: [PATCH] firebase errors and continue profress --- src/actions/signupActions.js | 26 +++++++++++------- src/screens/CreatePassword.js | 7 ++++- src/screens/Home/Home.js | 50 ++++++++++++++++++++++++++++------- src/screens/Login.js | 20 +++++++++++--- src/utils/projectStages.js | 40 ++++++++++++++++++++++++++-- 5 files changed, 117 insertions(+), 26 deletions(-) diff --git a/src/actions/signupActions.js b/src/actions/signupActions.js index ce062bd..4e6e6a2 100644 --- a/src/actions/signupActions.js +++ b/src/actions/signupActions.js @@ -38,37 +38,43 @@ export const formatPhoneNumber = ({ phoneNumber = null }) => { return newPhoneNumber; }; -export function handleFirebaseError(code) { +export function handleFirebaseError(code = "") { switch (code) { case "auth/user-not-found": return "Ce compte n'existe pas."; + case "auth/user-disabled": + return "Ce compte est désactivé. Contacte le support si besoin."; case "auth/invalid-verification-code": - return "Votre code de validation est incorrect."; + return "Ton code de validation est incorrect."; case "auth/provider-already-linked": return "Ce compte est déjà lié à un utilisateur."; case "auth/invalid-credential": - return "Identifiants incorrects."; + case "auth/invalid-login-credential": case "auth/invalid-login-credentials": return "Identifiants incorrects."; case "auth/credential-already-in-use": return "Ce compte existe déjà ou est déjà lié."; case "auth/operation-not-allowed": - return "Le provider n'est pas activé."; + return "Le fournisseur d'identité n'est pas disponible."; case "auth/invalid-email": - return "Email invalide."; + return "Adresse e-mail invalide."; case "auth/wrong-password": return "Mot de passe incorrect."; case "auth/invalid-verification-id": - return "Impossible de vous authentifié, réessayez dans quelques secondes."; + return "Impossible de t'authentifier, réessaie dans quelques secondes."; case "auth/invalid-phone-number": return "Numéro de téléphone incorrect."; case "auth/too-many-requests": - return "Nous avons détecté une activité inhabituelle et avons bloqué momentanément votre requête, réessayez dans quelques minutes."; + return "Trop de tentatives. Réessaie dans quelques minutes."; case "auth/email-already-in-use": - return "Il y a déjà un compte avec cette adresse mail."; + return "Il existe déjà un compte avec cette adresse e-mail."; case "auth/missing-password": - return "Veuillez entrer un mot de passe."; + return "Renseigne ton mot de passe."; + case "auth/weak-password": + return "Ton mot de passe est trop faible."; + case "auth/network-request-failed": + return "Problème de connexion réseau. Vérifie ta connexion et réessaie."; default: - return code; + return "Une erreur est survenue. Réessaie dans quelques instants."; } } diff --git a/src/screens/CreatePassword.js b/src/screens/CreatePassword.js index a049b8b..3ff24cd 100644 --- a/src/screens/CreatePassword.js +++ b/src/screens/CreatePassword.js @@ -6,6 +6,7 @@ import { background } from "../assets"; import GradientButton from "../components/GradientButton"; import { Input } from "../components/Input"; import ItemContainer from "../components/ItemContainer/ItemContainer"; +import { handleFirebaseError } from "../actions/signupActions"; import firebase, { usersRef } from "../config/firebase"; import Page from "../layouts/Page"; import { Routes } from "../navigation"; @@ -72,7 +73,11 @@ const CreatePassword = () => { navigate(Routes.CreatePseudo); } catch (e) { console.log("Register error", e?.message); - setTooltip({ text: e?.message || "Création impossible", type: "error" }); + const message = + e?.code && e.code.startsWith("auth/") + ? handleFirebaseError(e.code) + : e?.message || "Création impossible"; + setTooltip({ text: message, type: "error" }); } finally { setLoading(false); } diff --git a/src/screens/Home/Home.js b/src/screens/Home/Home.js index 6078ac1..33b64ba 100644 --- a/src/screens/Home/Home.js +++ b/src/screens/Home/Home.js @@ -75,12 +75,31 @@ const Home = () => { [currentProject] ); - const firstUnlockedIndex = useMemo(() => { - const index = stageStates.findIndex((stage) => !stage.isLocked); - return index === -1 ? 0 : index; + const preferredStageIndex = useMemo(() => { + if (!stageStates.length) { + return 0; + } + const actionableIndex = stageStates.findIndex( + (stage) => !stage.isCompleted && !stage.isLocked + ); + if (actionableIndex !== -1) { + return actionableIndex; + } + const firstIncomplete = stageStates.findIndex( + (stage) => !stage.isCompleted + ); + if (firstIncomplete !== -1) { + return firstIncomplete; + } + const firstUnlocked = stageStates.findIndex((stage) => !stage.isLocked); + if (firstUnlocked !== -1) { + return firstUnlocked; + } + return stageStates.length - 1; }, [stageStates]); - const [activeStageIndex, setActiveStageIndex] = useState(firstUnlockedIndex); + const [activeStageIndex, setActiveStageIndex] = + useState(preferredStageIndex); const [menuVisible, setMenuVisible] = useState(false); const [menuAnchor, setMenuAnchor] = useState(null); const [menuProject, setMenuProject] = useState(null); @@ -89,17 +108,28 @@ const Home = () => { useEffect(() => { setActiveStageIndex((prev) => { + const fallbackIndex = + preferredStageIndex >= 0 && preferredStageIndex < stageStates.length + ? preferredStageIndex + : 0; + if (prev == null || prev >= stageStates.length) { - return firstUnlockedIndex; + return fallbackIndex; } const current = stageStates[prev]; - const fallback = stageStates[firstUnlockedIndex]; - if (current?.isLocked && fallback && !fallback.isLocked) { - return firstUnlockedIndex; + if (!current) { + return fallbackIndex; + } + if ( + (current.isLocked || current.isCompleted) && + fallbackIndex !== prev && + stageStates[fallbackIndex] + ) { + return fallbackIndex; } return prev; }); - }, [stageStates, firstUnlockedIndex]); + }, [stageStates, preferredStageIndex]); const handleSelectProject = useCallback( (project) => { @@ -182,7 +212,7 @@ const Home = () => { }, [handleDeleteProject, menuProject?.id]); const activeStage = - stageStates[activeStageIndex] || stageStates[firstUnlockedIndex]; + stageStates[activeStageIndex] || stageStates[preferredStageIndex]; const stageAction = useMemo(() => { if (!activeStage) { return null; diff --git a/src/screens/Login.js b/src/screens/Login.js index 126c9f5..1ae17c7 100644 --- a/src/screens/Login.js +++ b/src/screens/Login.js @@ -19,6 +19,7 @@ import { background } from "../assets"; import GradientButton from "../components/GradientButton.js"; import { Input } from "../components/Input.js"; import ItemContainer from "../components/ItemContainer/ItemContainer"; +import { handleFirebaseError } from "../actions/signupActions.js"; import firebase, { usersRef } from "../config/firebase"; import { GOOGLE_ANDROID_CLIENT_ID, @@ -78,7 +79,11 @@ export default ({ navigation }) => { await afterLoginNavigate(); } catch (e) { console.log("Login error", e?.message); - setTooltip({ text: e?.message || "Connexion impossible", type: "error" }); + const message = + e?.code && e.code.startsWith("auth/") + ? handleFirebaseError(e.code) + : e?.message || "Connexion impossible"; + setTooltip({ text: message, type: "error" }); } finally { setLoading(false); } @@ -104,8 +109,13 @@ export default ({ navigation }) => { } } catch (e) { console.log("Google Login error", e?.message); + const message = + e?.code && e.code.startsWith("auth/") + ? handleFirebaseError(e.code) + : e?.message; setTooltip({ - text: e?.message || "Connexion Google impossible. Merci de réessayer.", + text: + message || "Connexion Google impossible. Merci de réessayer.", type: "error", }); setLoading(false); @@ -165,8 +175,12 @@ export default ({ navigation }) => { } } catch (e) { console.log("Google native sign-in error", e?.message); + const message = + e?.code && e.code.startsWith("auth/") + ? handleFirebaseError(e.code) + : e?.message; setTooltip({ - text: e?.message || "Connexion Google impossible", + text: message || "Connexion Google impossible", type: "error", }); } finally { diff --git a/src/utils/projectStages.js b/src/utils/projectStages.js index eb0692f..32fc3dd 100644 --- a/src/utils/projectStages.js +++ b/src/utils/projectStages.js @@ -147,6 +147,21 @@ const getStageLockedDescription = (key, metadata) => { } }; +const getStageCompletionState = (key, metadata) => { + switch (key) { + case "songwriter": + return metadata.hasLyrics; + case "beatmaker": + return metadata.hasSongUrl || metadata.musicStatus === "GENERATED"; + case "designer": + return metadata.hasCover; + case "director": + return metadata.hasPlaybackAsset; + default: + return false; + } +}; + export const getCreationStageStates = (project) => { const metadata = getStageMetadata(project); return CREATION_STAGE_KEYS.map((key, index) => { @@ -158,6 +173,7 @@ export const getCreationStageStates = (project) => { key, index, isLocked, + isCompleted: getStageCompletionState(key, metadata), description: isLocked && lockedDescription ? lockedDescription : description, lockedDescription, @@ -198,6 +214,26 @@ export const getStageAction = (key, project) => { export const findFirstUnlockedStageIndex = (project) => { const stages = getCreationStageStates(project); - const index = stages.findIndex((stage) => !stage.isLocked); - return index === -1 ? 0 : index; + if (!stages.length) { + return 0; + } + + const actionableIndex = stages.findIndex( + (stage) => !stage.isCompleted && !stage.isLocked + ); + if (actionableIndex !== -1) { + return actionableIndex; + } + + const firstIncomplete = stages.findIndex((stage) => !stage.isCompleted); + if (firstIncomplete !== -1) { + return firstIncomplete; + } + + const firstUnlocked = stages.findIndex((stage) => !stage.isLocked); + if (firstUnlocked !== -1) { + return firstUnlocked; + } + + return stages.length - 1; };