diff --git a/apps/mobile/README.md b/apps/mobile/README.md index 5db17d5..3ef9f55 100644 --- a/apps/mobile/README.md +++ b/apps/mobile/README.md @@ -73,6 +73,8 @@ export const api = initClient(apiContract, { ## 🔐 Flux d'authentification +L'authentification utilise un **Context React** pour gérer l'état global de la session. + ### 1. Connexion ```typescript const { data, error } = await authClient.signIn.email({ @@ -90,12 +92,24 @@ if (sessionData.data) { } ``` -### 3. Déconnexion +### 3. Déconnexion (via Context) ```typescript -await authClient.signOut(); -setSession(null); +import { useAuth } from './components/AuthProvider'; + +export default function AccountScreen() { + const { logout } = useAuth(); + + const handleLogout = async () => { + await logout(); // Déconnexion + redirection automatique vers LoginScreen + }; +} ``` +Le pattern avec `useAuth()` permet : +- ✅ Accès global à la fonction de déconnexion +- ✅ Redirection automatique vers le LoginScreen +- ✅ Pas de prop drilling + ## 🧩 Intégration des packages partagés L'app mobile utilise tous les packages partagés du monorepo : @@ -159,6 +173,104 @@ pnpm --filter api dev 2. Scanner le QR code affiché dans le terminal 3. L'app se charge avec l'écran de connexion +## 📦 Build et déploiement de l'APK + +### Prérequis +- Compte Expo créé et authentifié : `npx eas login` +- Projet EAS configuré + +### Profils de build disponibles + +Le projet utilise **EAS Build** avec 3 profils configurés dans `eas.json` : + +| Profil | Usage | API URL | +|--------|-------|---------| +| `development` | Dev avec hot reload | Variable d'env locale | +| `preview` | Test en prod (APK) | `https://api.dropit-app.fr` | +| `production` | Publication Play Store | Variable d'env prod | + +### Build d'un APK pour tester (Preview) + +```bash +# Se placer dans le dossier mobile +cd apps/mobile + +# Build APK avec le profil preview (connecté à l'API de prod) +npx eas build --platform android --profile preview + +# Le build se fait dans le cloud Expo +# Temps estimé : 5-10 minutes +# Vous recevrez un lien pour télécharger l'APK +``` + +### Build local (plus rapide) + +```bash +# Build local sans utiliser les serveurs Expo +npx eas build --platform android --profile preview --local + +# Nécessite Android SDK installé localement +``` + +### Installation de l'APK sur votre téléphone + +1. Une fois le build terminé, EAS vous donne un **lien de téléchargement** +2. Téléchargez l'APK sur votre téléphone +3. Activez "Sources inconnues" dans les paramètres Android +4. Installez l'APK + +### Variables d'environnement + +Le profil **preview** utilise automatiquement : +```bash +EXPO_PUBLIC_API_URL=https://api.dropit-app.fr +``` + +Pour changer l'URL de l'API, modifiez `eas.json` : +```json +{ + "build": { + "preview": { + "env": { + "EXPO_PUBLIC_API_URL": "https://votre-api.com" + } + } + } +} +``` + +### Commandes utiles EAS + +```bash +# Lister les builds précédents +npx eas build:list + +# Voir les détails d'un build +npx eas build:view [BUILD_ID] + +# Build iOS (nécessite compte Apple Developer) +npx eas build --platform ios --profile preview + +# Soumettre à Google Play Store (production) +npx eas submit --platform android +``` + +### Troubleshooting builds + +**Erreur "Not logged in"** +```bash +npx eas login +``` + +**Build qui échoue** +```bash +# Vérifier les logs détaillés sur : +# https://expo.dev/accounts/[votre-compte]/projects/dropit-mobile/builds +``` + +**APK trop gros** +- Utilisez le profil `production` qui active Hermes et optimise automatiquement + ## 🔧 Configuration réseau Pour tester sur un appareil physique, assurez-vous que : diff --git a/apps/mobile/src/components/AccountScreen.tsx b/apps/mobile/src/components/AccountScreen.tsx index 2417c81..5612edd 100644 --- a/apps/mobile/src/components/AccountScreen.tsx +++ b/apps/mobile/src/components/AccountScreen.tsx @@ -8,7 +8,7 @@ import { Alert, } from 'react-native'; import { StatusBar } from 'expo-status-bar'; -import { authClient } from '../lib/auth-client'; +import { useAuth } from './AuthProvider'; import BottomNavigation from './BottomNavigation'; interface AccountScreenProps { @@ -16,6 +16,8 @@ interface AccountScreenProps { } export default function AccountScreen({ onTabPress }: AccountScreenProps) { + const { logout } = useAuth(); + const handleLogout = async () => { Alert.alert( 'Déconnexion', @@ -27,8 +29,7 @@ export default function AccountScreen({ onTabPress }: AccountScreenProps) { style: 'destructive', onPress: async () => { try { - await authClient.signOut(); - // L'AuthProvider détectera automatiquement la déconnexion + await logout(); } catch (error) { console.error('Logout error:', error); Alert.alert('Erreur', 'Erreur lors de la déconnexion'); diff --git a/apps/mobile/src/components/AuthProvider.tsx b/apps/mobile/src/components/AuthProvider.tsx index 5316d79..e20fd3e 100644 --- a/apps/mobile/src/components/AuthProvider.tsx +++ b/apps/mobile/src/components/AuthProvider.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, createContext, useContext } from 'react'; import { View, Text, ActivityIndicator, StyleSheet } from 'react-native'; import { authClient } from '../lib/auth-client'; import LoginScreen from './LoginScreen'; @@ -24,6 +24,20 @@ interface Session { }; } +interface AuthContextType { + logout: () => Promise; +} + +const AuthContext = createContext(null); + +export const useAuth = () => { + const context = useContext(AuthContext); + if (!context) { + throw new Error('useAuth must be used within AuthProvider'); + } + return context; +}; + export default function AuthProvider({ children }: AuthProviderProps) { const [session, setSession] = useState(null); const [isLoading, setIsLoading] = useState(true); @@ -64,13 +78,14 @@ export default function AuthProvider({ children }: AuthProviderProps) { await initializeAuth(); }; - const handleLogout = async () => { + const logout = async () => { try { await authClient.signOut(); setSession(null); console.log('Logged out successfully'); } catch (error) { console.error('Logout error:', error); + throw error; } }; @@ -91,10 +106,11 @@ export default function AuthProvider({ children }: AuthProviderProps) { // Session active, afficher l'app return ( - - {children} - {/* Vous pouvez ajouter un bouton de déconnexion ici pour les tests */} - + + + {children} + + ); } diff --git a/apps/mobile/src/components/BottomNavigation.tsx b/apps/mobile/src/components/BottomNavigation.tsx index a7b6707..25ed3cb 100644 --- a/apps/mobile/src/components/BottomNavigation.tsx +++ b/apps/mobile/src/components/BottomNavigation.tsx @@ -57,8 +57,8 @@ export default function BottomNavigation({ activeTab, onTabPress }: BottomNaviga const styles = StyleSheet.create({ container: { - paddingBottom: 40, // Safe area for iPhone - paddingTop: 20, + paddingBottom: 50, + paddingTop: 10, backgroundColor: '#191d26', }, navigationBar: {