Phase 4 · En cours Android + iOS natifs

Application Mobile

L'app mobile native iOS + Android. Parité fonctionnelle complète avec le portail web (mêmes endpoints, même flow OTP) + capacités natives : biométrie, caméra KYC, notifications push, fonctionnement offline.

2
Plateformes natives
100%
Code UI partagé Android/iOS
Natif
Pas de WebView, perf native

📸 Captures émulateur Android

Captures réelles prises sur émulateur Android Pixel 10 Pro (API 36), APK debug installé, connecté à un backend NestJS local avec données démo (Mohamed Ben Salah, +216 55 101 001, prêt actif AA-2026-001 en retard).

Les écrans présentés sont ceux qui s'affichent réellement aujourd'hui. Les sections marquées À FAIRE dans le tableau d'état plus bas ne figurent pas ici (biométrie, caméra KYC, push, bascule RTL — non implémentés).

1. Authentification OTP par SMS

Flow login standard : sélection pays Tunisie (préfixe +216 verrouillé), saisie numéro, envoi du code à 6 chiffres, vérification, navigation automatique vers le dashboard. Aucun mot de passe.

Écran de connexion vide
Login — Marque Qredon, pays Tunisie présélectionné
Numéro saisi
Numéro saisi — Bouton « Continuer » activé
Écran OTP vide
OTP vide — Compteur expiration + renvoi du code
OTP rempli
OTP saisi — 6 chiffres répartis en cases

2. Tableau de bord & prêt actif

Vue d'ensemble pour un emprunteur avec un prêt actif DISBURSED en statut LATE (échéancier de 6 mensualités : 4 payées, 1 en retard, 1 à venir).

Dashboard
Dashboard — Salutation, prêt actif, demande en cours, bottom nav 4 onglets
Mon prêt actif
Mon prêt actif — Récap montants, échéancier 6 lignes avec statuts
Détail demande
Détail demande — Progression % + chronologie 5 étapes

3. Simulateur de prêt

3 produits seedés (Micro Credit Express 18%, Prêt Équipement 12%, Prêt Solidaire Groupe 15%). Saisie montant + durée, calcul de la mensualité, des intérêts, et propositions de scénarios alternatifs (durées différentes).

Simulateur vide
Simulateur — Choix produit + montant + durée
Résultat simulation
Résultat — Mensualité 275 TND, total intérêts, scénarios alternatifs

4. Nouvelle demande & suivi

Wizard 5 étapes (produit → montant/durée → motif → documents → signature) + écran de suivi listant les demandes en cours avec leur statut.

Wizard étape 1
Wizard étape 1/5 — Choix du produit
Wizard étape 2
Wizard étape 2/5 — Montant & durée (avec bornes du produit)
Suivi des demandes
Suivi des demandes — Liste avec statuts (« Demande reçue », « Prêt décaissé »)

5. Profil emprunteur & sécurité

Profil complet (KYC VERIFIED, 100% complétude) avec accès aux sessions actives, journal d'activité, documents et notifications. Token JWT stocké de manière chiffrée sur l'appareil (session persiste après fermeture de l'app).

Mon profil
Mon profil — KYC, CIN masquée, email, adresse, langue
Sessions actives
Sessions actives — Liste avec IP masquée, bouton Révoquer
Journal d'activité
Journal d'activité — Trace des connexions de l'emprunteur

6. États vides & écrans annexes

Historique vide
Historique — Empty state « Aucun historique de prêt »
Notifications vide
Notifications — Empty state « Aucune notification »
Mes documents
Mes documents — Empty state « Aucun document disponible » (crash JSON corrigé)

Correctifs appliqués depuis la première capture (recapturé sur émulateur en français) :

  • ✅ Les dates sont désormais formatées (1 avr. 2026, il y a 60 jours) via une infra i18n FR/EN/AR — fini l'ISO brut.
  • ✅ L'écran Mes documents charge sans crash (le contrat API renvoyait un tableau au lieu d'un objet enveloppé — corrigé côté serveur).
  • ✅ Le logout (icône ⏻) est couvert par un test unitaire ViewModel ; la vérification end-to-end sur device reste à faire.
  • ⏳ Aucun écran ne demande encore de biométrie / Face ID / empreinte — feature native non implémentée (voir tableau ci-dessous).

✨ Fonctionnalités

Parité avec le portail web (mêmes endpoints, même flow OTP) + spécifiques mobile :

📱 Login OTP

SMS 6 chiffres, identique au portail. Stockage du token chiffré dans le coffre-fort sécurisé du système.

🔐 Biométrie

Reconnexion silencieuse Face ID / Touch ID / empreinte après opt-in depuis le profil.

📷 Caméra KYC

Capture CIN recto/verso + selfie avec overlay. Liveness 3 photos (face, gauche, droite).

🔔 Push natif

Notifications push FCM (Android) et APNs (iOS). Deep links vers l'écran concerné.

💰 Demande de prêt

Wizard identique au portail web — signature OTP de consentement.

📄 Documents + reçus

Téléchargement PDF, partage natif via share sheet iOS / Intent Android.

📡 Offline

Lecture des données récentes sans connexion, mutations bloquées avec message clair.

🌐 Multilingue

FR / AR (avec RTL natif) / EN — basculable depuis les paramètres de l'app.

🔐 Authentification + biométrie

Premier login : OTP SMS (comme le portail web). Après le premier login, opt-in possible pour la biométrie depuis la page Profil > Sécurité.

Une fois la biométrie activée, les sessions suivantes sont silencieuses :

  1. L'utilisateur ouvre l'app
  2. Face ID / Touch ID / empreinte demandé
  3. En cas de succès → token déchiffré et utilisateur connecté immédiatement
  4. En cas d'échec → fallback OTP SMS

⚠️ Pour des raisons de sécurité, le PIN du téléphone n'est pas accepté comme alternative à la biométrie (la biométrie est la seule preuve).

📷 Caméra KYC

Capture native (qualité supérieure à un upload via la galerie) :

  • CIN recto/verso — overlay rectangulaire pour guider le cadrage
  • Selfie KYC — overlay circulaire pour le visage
  • Liveness 3 photos — séquence face → gauche → droite (anti-fraude minimal)

Les images sont uploadées directement au backend après capture, jamais stockées de manière permanente sur le téléphone.

🔔 Notifications push natives

L'app reçoit des notifications push pour les événements importants :

  • Prêt approuvé / rejeté / décaissé
  • Échéance de remboursement dans 3 jours
  • Paiement confirmé
  • Demande de complément KYC
  • Statut KYC changé

Un tap sur la notification ouvre directement l'écran concerné (deep link) au lieu de la home.

📡 Fonctionnement offline

L'app fonctionne même sans connexion pour :

  • Consulter son dashboard et son prêt actif
  • Voir l'historique des paiements
  • Voir ses documents déjà téléchargés
  • Voir ses notifications

Les mutations (signature, soumission demande, etc.) nécessitent un réseau actif. Un bandeau "Hors ligne" s'affiche automatiquement en cas de coupure.

📊 État actuel

Validé par observation directe sur émulateur Android (Pixel 10 Pro, API 36) le 2026-05-24 contre un backend NestJS local avec données démo seedées.

Socle fonctionnel

ComposantStatutNote
Structure projet KMP (Android + iOS + code partagé Compose)DONECompose Multiplatform 1.10, Kotlin 2.3
Design system (charte Émeraude/Cuivre, typo Inter)DONECohérent avec portail web
Navigation entre écrans + bottom nav 4 ongletsDONESimulateur / Demande / Suivi / Historique
Couche data Ktor + sérialisationDONEAPI Portal NestJS, header x-tenant-slug
Stockage sécurisé tokens (session persistante)DONEVérifié : reconnexion sans OTP après fermeture de l'app
Formatage des dates localisé (FR / EN / AR)DONEInfra LocaleProvider + DateFormat (expect/actual), 15 tests. Convention Tunisie : chiffres latins + mois en arabe

Écrans implémentés et validés

ÉcranStatutNote
Login (sélection pays + numéro)DONEPréfixes MENA, validation min 6 chiffres
OTP SMS (saisie 6 chiffres, compteur, renvoi)DONEDélai 5 min + délai renvoi
Dashboard (prêt actif + demandes en cours)DONE
Détail prêt actif (montants + échéancier complet)DONEStatuts par échéance : Payé / Retard / À venir
Détail demande (chronologie 5 étapes + %)DONE
Wizard nouvelle demande (5 étapes)DONEÉtapes 1 & 2 validées (produit, montant/durée)
Suivi des demandesDONE
Historique des prêts (avec empty state)DONE
Simulateur de prêt + scénarios alternatifsDONECalcul mensualité, intérêts, frais
Profil emprunteur (KYC, CIN masquée, complétude)DONE
Sessions actives (avec révocation)DONE
Journal d'activitéDONEHistorique des connexions
Centre de notifications (avec empty state)DONE

À faire / capacités natives non implémentées

ComposantStatutNote
Biométrie (Face ID / Touch ID / empreinte)À FAIREAucun écran ne propose l'activation aujourd'hui
Caméra KYC (capture CIN recto/verso + selfie)À FAIREÉcran existe (DocumentUploadScreen) mais flow natif caméra non testé
Liveness 3 photos (face / gauche / droite)À FAIREÉcran existe (LivenessScreen) mais non vérifié
Push notifications natives (FCM Android + APNs iOS)À FAIREBackend Portal compatible, intégration mobile à faire
Bascule de langue FR / AR (RTL) / EN dans l'UIÀ FAIRELe formatage des dates est déjà localisé FR/EN/AR (infra LocaleProvider + DateFormat), mais le sélecteur de langue dans les paramètres et le layout RTL restent à câbler
Mode offline (cache local SQLDelight)À FAIREBandeau hors-ligne non observé
Tests E2E automatisés (exécution)PARTIELMaestro installé + 3 flows écrits (_login, dates-formatted, logout) ; exécution live + endpoint dev OTP renvoyés au sous-projet suivant

🐛 Bugs observés lors des captures → corrigés

La première campagne de captures avait révélé 3 défauts. Ils ont été corrigés en TDD (tests d'abord), puis les écrans concernés ont été recapturés (ce sont les images ci-dessus).

BugSévéritéStatutCorrectif
Écran « Mes documents » plante au chargementBLOQUANTCORRIGÉL'API renvoyait un tableau au lieu de l'objet { applications: [] } déclaré (cast as unknown as trompeur). Aligné côté serveur + hook web ; le DTO mobile était déjà correct. 3 tests serveur qui échouaient en silence passent désormais.
Dates affichées en ISO brutUXCORRIGÉMini-infra i18n KMP (formatDate / formatRelative, FR/EN/AR, chiffres latins). 11 écrans câblés. 15 tests unitaires. 2026-04-01T00:00:00.000Z1 avr. 2026 ; Dans -53 jour(s)il y a 53 jours.
Bouton logout non validéUXTESTÉ (unit)Test unitaire DashboardViewModel.logout() ajouté (refacto AuthRepositoryContract pour la testabilité). Vérification end-to-end sur device encore à faire.

📥 Installation pour test

L'app n'est pas encore publiée sur les stores. Pour tester sur un appareil :

Android

  1. Recevoir le fichier APK debug par AirDrop / email / lien
  2. Sur le téléphone Android : activer "Sources inconnues" dans les paramètres
  3. Installer l'APK
  4. Ouvrir Qredon → écran de login

iOS

  1. Inscription du device dans le profil de provisioning (Apple Developer)
  2. Installation via TestFlight ou directement via Xcode
  3. Lancer l'app → écran de login

🧪 Tous les scénarios de test

Catalogue des scénarios pour l'app mobile. Les scénarios de base sont communs avec le portail web (même API).

A. Premier lancement & login OTP (8 scénarios)
  1. 1
    Premier lancement — Ouvrir l'app pour la première fois → écran de bienvenue + sélection langue.
  2. 2
    Login OTP standard — Saisir +216 55 101 001 → SMS reçu sur MailHog → saisir code → connecté.
  3. 3
    Demande de permissions — L'app demande permissions Push notifications + Caméra à l'installation.
  4. 4
    Refus permission caméra — L'utilisateur refuse → message explicatif quand on tente une action caméra.
  5. 5
    Refus permission push — L'utilisateur refuse → l'app fonctionne mais sans push (toast au lieu de notif).
  6. 6
    Code OTP incorrect — Saisir 6 chiffres faux → message "Code invalide".
  7. 7
    Code OTP expiré (5 min) — Trop attendre → "Code expiré" + bouton "Recevoir un nouveau code".
  8. 8
    Réseau coupé pendant le login — Désactiver wifi pendant la saisie du code → message "Connexion requise pour la vérification".
B. Biométrie (10 scénarios)
  1. 1
    Activer Face ID (iOS) — Connecté → Profil → Sécurité → "Activer Face ID" → confirmation Face ID → activé.
  2. 2
    Activer Touch ID (iOS ancien) — Idem Face ID mais avec empreinte.
  3. 3
    Activer empreinte (Android) — Profil > Sécurité > "Activer biométrie" → empreinte → activé.
  4. 4
    Reconnexion biométrique — Fermer l'app, la rouvrir → Face ID demandé → succès → connecté instantanément (pas d'OTP).
  5. 5
    Échec biométrique — 3 échecs Face ID → bascule sur écran OTP (fallback).
  6. 6
    Annulation biométrique — Bouton "Annuler" sur le prompt biométrique → écran OTP affiché.
  7. 7
    Désactiver biométrie — Profil > Sécurité → "Désactiver" → confirmation biométrique requise → désactivé + token effacé du coffre.
  8. 8
    Appareil sans biométrie — Téléphone sans Face ID / empreinte → option grisée avec message "Non disponible sur cet appareil".
  9. 9
    PIN device refusé — Le PIN du téléphone n'est pas accepté comme fallback de la biométrie (volontaire).
  10. 10
    Logout wipe — Logout depuis le profil → token effacé du coffre → prochaine ouverture demande OTP.
C. Caméra KYC (8 scénarios)
  1. 1
    Capture CIN recto — Étape Documents lors de l'inscription → "Capturer CIN recto" → caméra ouverte avec overlay rectangulaire → capture → preview.
  2. 2
    Capture CIN verso — Idem mais pour le verso.
  3. 3
    Selfie KYC — Overlay circulaire centré sur le visage → capture → preview.
  4. 4
    Liveness 3 photos — Séquence guidée : "Regardez devant" → photo. "Tournez à gauche" → photo. "Tournez à droite" → photo.
  5. 5
    Reprendre la photo — Bouton "Reprendre" sur le preview → recapture.
  6. 6
    Lumière insuffisante — Capture trop sombre → message d'avertissement, suggestion de reprendre.
  7. 7
    Permission caméra refusée initialement — Si l'utilisateur a refusé, message explicatif + lien vers les paramètres système.
  8. 8
    Upload après capture — Photos uploadées au backend après validation → progression visible.
D. Push notifications (8 scénarios)
  1. 1
    Push "Prêt approuvé" — IMF approuve le prêt → push sur le téléphone avec son + vibration.
  2. 2
    Push "Prêt décaissé" — IMF décaisse → push avec montant et date.
  3. 3
    Push "Échéance dans 3 jours" — 3 jours avant l'échéance → push de rappel.
  4. 4
    Push "Paiement confirmé" — Caissier enregistre le paiement → push immédiat à l'emprunteur.
  5. 5
    Push "Complément KYC requis" — IMF demande un doc supplémentaire → push.
  6. 6
    Deep link au tap — Tap sur la push "Prêt approuvé" → l'app s'ouvre directement sur la page du prêt concerné.
  7. 7
    Push reçu app fermée — Push reçu alors que l'app n'est pas lancée → notification système → tap ouvre l'app au bon endroit.
  8. 8
    Désactiver push — Paramètres iOS/Android → couper les notifs pour Qredon → plus de push reçues mais l'app fonctionne.
E. Demande de prêt depuis mobile (6 scénarios)
  1. 1
    Demande complète depuis le mobile — Connecté → "Demander un prêt" → wizard 4 étapes → signature OTP → soumise (identique au portail web).
  2. 2
    Sauvegarde brouillon — Quitter l'app au milieu du wizard → revenir → reprise où on en était.
  3. 3
    Upload pièces via caméra — Étape Documents → "Capturer avec la caméra" au lieu d'upload galerie.
  4. 4
    Signature OTP — À la soumission → OTP envoyé → saisie → demande soumise.
  5. 5
    Continuer une demande commencée sur web — Brouillon créé sur le portail web → reprise dans l'app mobile (même compte).
  6. 6
    Annuler une demande — Si statut DRAFT ou SUBMITTED → bouton "Annuler".
F. Fonctionnement offline (5 scénarios)
  1. 1
    Mode avion activé — Ouvrir l'app sans réseau → bandeau "Hors ligne" → dashboard, prêt actif, historique consultables (depuis cache).
  2. 2
    Mutation bloquée offline — Tenter une demande de prêt sans réseau → message "Connexion requise pour cette action".
  3. 3
    Reconnexion auto — Désactiver mode avion → bandeau "Hors ligne" disparaît → données rafraîchies.
  4. 4
    Push reçue en différé — Push envoyée pendant que le téléphone était offline → reçue dès le retour en ligne.
  5. 5
    Cache expiré — Cache local de >24h → l'app force le refresh au retour en ligne.
G. Multilingue & RTL (4 scénarios)
  1. 1
    Bascule en arabe — Paramètres > Langue > العربية → toute l'UI bascule + layout RTL.
  2. 2
    Bascule en anglais — Choisir English → UI en anglais.
  3. 3
    Persistance après redémarrage — Fermer l'app, rouvrir → langue conservée.
  4. 4
    Langue système par défaut — Premier lancement → l'app détecte la langue du système et l'utilise par défaut.
H. Documents & partage natif (5 scénarios)
  1. 1
    Voir mes documents — Documents → liste de tous mes docs uploadés.
  2. 2
    Télécharger un reçu PDF — Reçu d'un paiement → "Télécharger" → PDF généré.
  3. 3
    Partager via share sheet — Bouton "Partager" → share sheet natif (WhatsApp, email, AirDrop iOS, Intent Android).
  4. 4
    Générer attestation — Documents > Générer > Bonne tenue → PDF généré + QR.
  5. 5
    Ouvrir le PDF directement — Tap sur un PDF → ouverture dans le viewer natif iOS/Android.
I. Edge cases mobile (8 scénarios)
  1. 1
    Mise en arrière-plan — App en background pendant un appel/SMS → reprise au même endroit.
  2. 2
    Rotation de l'écran — Tourner le téléphone → l'app reste utilisable (portrait par défaut, paysage géré).
  3. 3
    Faible mémoire — Système low-memory → l'app gère le redémarrage propre sans perte de données.
  4. 4
    Batterie faible — L'app continue de fonctionner normalement (pas de mode dégradé).
  5. 5
    Mise à jour de l'app — Update via store → ouverture après update → re-connexion biométrique ou OTP si nécessaire.
  6. 6
    Désinstallation/réinstallation — Désinstaller l'app → token wipe automatique → réinstaller → premier login OTP requis.
  7. 7
    Compte sur deux appareils — Même compte connecté sur 2 téléphones → les deux fonctionnent, les notifs arrivent sur les deux.
  8. 8
    Tenant suspendu — L'IMF est suspendue → l'app affiche un message "Service indisponible, contactez votre conseiller".
J. Workflows complets bout-à-bout (3 scénarios)
  1. 1
    Onboarding emprunteur 100% mobile
    1. Installation de l'app Android/iOS
    2. Premier lancement → Sélection langue (FR/AR/EN)
    3. "Créer un compte" → saisie phone + email
    4. Réception double OTP → validation
    5. Saisie profil de base
    6. Capture CIN recto/verso via caméra native
    7. Selfie KYC + liveness 3 photos
    8. Soumission → statut PENDING_REVIEW
    9. Activation biométrie proposée pour les prochaines sessions
    10. Validation par l'agent IMF → push reçue "KYC validé"
    11. Tap sur la push → écran statut KYC affiché
  2. 2
    Cycle prêt + remboursement sur mobile
    1. Réouverture de l'app → Face ID → connecté instantanément
    2. Tap "Demander un prêt" → wizard 4 étapes
    3. Soumission + signature OTP → dossier créé
    4. 3 jours plus tard → push "Prêt approuvé" → tap → écran du prêt
    5. 2 jours plus tard → push "Prêt décaissé" + montant
    6. 30 jours plus tard → push "Échéance dans 3 jours"
    7. L'utilisateur se rend à l'agence et paie en cash
    8. Push immédiate "Paiement confirmé" → reçu PDF téléchargeable
    9. Partage du reçu via WhatsApp à son comptable (share sheet natif)
  3. 3
    Utilisation offline en zone rurale
    1. Emprunteur dans une zone sans réseau → ouvre l'app
    2. Bandeau "Hors ligne" affiché
    3. Il consulte son prêt actif et son échéancier (cache local)
    4. Il télécharge ses derniers reçus pour les partager plus tard
    5. De retour en ville avec réseau → bandeau "Hors ligne" disparaît
    6. Les push en attente arrivent
    7. Les données se rafraîchissent automatiquement