welloo_sdk 0.0.108 copy "welloo_sdk: ^0.0.108" to clipboard
welloo_sdk: ^0.0.108 copied to clipboard

Package de transaction Welloo

example/lib/main.dart

import 'dart:async';

import 'package:example/auth_service.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:welloo_sdk/welloo_sdk.dart';

// 1. DÉCLARATION GLOBALE DE LA CLÉ DE NAVIGATION
// Cela permet d'accéder au navigateur depuis n'importe où (même hors du contexte)
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 2. CHARGEMENT DES VARIABLES D'ENVIRONNEMENT

  runApp(const MainApp());
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welloo SDK - Nouveau Système',
      // 3. INJECTION DE LA CLÉ DANS MATERIAL APP
      navigatorKey: navigatorKey,
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
      ),
      home: const DemoWello(),
    );
  }
}

class DemoWello extends StatefulWidget {
  const DemoWello({super.key});

  @override
  State<DemoWello> createState() => _DemoWelloState();
}

class _DemoWelloState extends State<DemoWello> {
  bool _isLoggedIn = false;
  bool _isLoading = false; // Pour afficher un spinner
  final TextEditingController _phoneController = TextEditingController();
  final TextEditingController _pineController = TextEditingController();
  final AuthService _authService = AuthService();

  // Getters pour sécuriser l'accès aux variables d'env
  String _accessToken = "";
  String _refreshToken = '';

  StreamSubscription<Uri>? _linkSubscription;

  @override
  void initState() {
    super.initState();

    _phoneController.text = "0707860944";
    _pineController.text = "1945";
  }

  @override
  void dispose() {
    _linkSubscription?.cancel();
    super.dispose();
  }

  void _handleLogin() async {
    setState(() => _isLoading = true);
    // 👇 Demande la permission contacts AVANT de lancer le SDK
    final status = await Permission.contacts.request();

    if (status.isPermanentlyDenied) {
      // 👇 Redirige vers les paramètres si refus permanent
      await openAppSettings();
    }
    final result =
        await _authService.login(_phoneController.text, _pineController.text);

    setState(() => _isLoading = false);

    if (result != null) {
      setState(() {
        _accessToken = result['access_token'];
        _refreshToken = result['refresh_token'];
        _isLoggedIn = true;
      });
    } else {
      _showError("Identifiants incorrects ou erreur serveur");
    }
  }

  void _showError(String message) {
    ScaffoldMessenger.of(context)
        .showSnackBar(SnackBar(content: Text(message)));
  }

  // --- LOGIQUE DEEP LINK ---

  // --- HANDLERS DU SDK ---

  Future<void> _handleDepositNew() async {
    Navigator.of(context).push(MaterialPageRoute(
        builder: (_) => WellooDeposit(
              accessToken: _accessToken,
              refreshToken: _refreshToken,

              // ✅ Callback Succès
              onSuccess: (result) {
                debugPrint("🎉 SUCCÈS PAIEMENT");
                debugPrint("-------------------");
                debugPrint("Ref  : ${result.transactionId}");
                debugPrint("Info : ${result.description}");
              },

              // ❌ Callback Erreur (Refus, Annulation, Technique)
              onError: (error) {
                debugPrint("⚠️ ÉCHEC PAIEMENT");
                debugPrint("------------------");
                debugPrint("Cause : ${error.description}");
              },
            )));
  }

  // Future<void> _handleTransfer() async {
  //   Navigator.of(context).push(
  //     MaterialPageRoute(
  //       builder: (_) => WellooTransfer(
  //         accessToken: _accessToken,
  //         refreshToken: _refreshToken,
  //         // ✅ Callback Succès
  //         onSuccess: (result) {
  //           debugPrint("Info : ${result.description}");
  //         },
  //         // ❌ Callback Erreur
  //         onError: (error) {
  //           debugPrint("Error : ${error.description}");
  //         },
  //       ),
  //     ),
  //   );
  // }

  Future<void> _handleTransferNew() async {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => WellooTransfer(
          accessToken: _accessToken,
          refreshToken: _refreshToken,
          // ✅ Callback Succès
          onSuccess: (result) {
            debugPrint("Info : ${result.description}");
          },
          // ❌ Callback Erreur
          onError: (error) {
            debugPrint("Error : ${error.description}");
          },
        ),
      ),
    );
  }

  Future<void> _handleScanner() async {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (_) => WellooScanQr(
          accessToken: _accessToken,
          refreshToken: _refreshToken,
          // ✅ Callback Succès
          onSuccess: (result) {
            debugPrint("✅ Succès : ${result.description}");
          },
          // ❌ Callback Erreur
          onError: (error) {
            debugPrint("❌ Erreur : ${error.description}");
          },
        ),
      ),
    );
  }

  // --- UI ---

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Welloo SDK Demo'),
        centerTitle: true,
      ),
      backgroundColor: Colors.grey[100],
      body: Center(
        child: Padding(
          padding: const EdgeInsets.all(20.0),
          child: _isLoggedIn ? _buildMainMenu() : _buildLoginForm(),
        ),
      ),
    );
  }

  // Formulaire de connexion
  Widget _buildLoginForm() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Icon(Icons.account_circle, size: 100, color: Colors.blue),
        const SizedBox(height: 20),
        const Text("Bienvenue sur Welloo",
            style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
        const SizedBox(height: 30),
        TextField(
          controller: _phoneController,
          keyboardType: TextInputType.phone,
          decoration: InputDecoration(
            labelText: "Numéro de téléphone",
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
            prefixIcon: const Icon(Icons.phone),
          ),
        ),
        const SizedBox(height: 20),
        TextField(
          controller: _pineController,
          keyboardType: TextInputType.phone,
          decoration: InputDecoration(
            labelText: "Pin",
            border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
            prefixIcon: const Icon(Icons.lock),
          ),
        ),
        const SizedBox(height: 20),
        SizedBox(
          width: double.infinity,
          height: 55,
          child: ElevatedButton(
            onPressed: _handleLogin,
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.blue,
              foregroundColor: Colors.white,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12)),
            ),
            child: const Text("Se connecter", style: TextStyle(fontSize: 18)),
          ),
        ),
      ],
    );
  }

  // Votre menu actuel déplacé dans une fonction
  Widget _buildMainMenu() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        _buildMenuButton(
          icon: Icons.download,
          label: "Initier un Dépôt (v2)",
          onPressed: _handleDepositNew,
          color: Colors.green,
        ),
        const SizedBox(height: 20),
        _buildMenuButton(
          icon: Icons.send,
          label: "Initier un Transfert (V2)",
          onPressed: _handleTransferNew,
          color: Colors.blue,
        ),
        const SizedBox(height: 20),
        _buildMenuButton(
          icon: Icons.qr_code_scanner,
          label: "Scanner QR Code",
          onPressed: _handleScanner,
          color: Colors.purple,
        ),
      ],
    );
  }

  // Widget helper pour éviter la répétition de code
  Widget _buildMenuButton({
    required IconData icon,
    required String label,
    required VoidCallback onPressed,
    required Color color,
  }) {
    return SizedBox(
      width: double.infinity,
      height: 60,
      child: ElevatedButton.icon(
        onPressed: onPressed,
        icon: Icon(icon),
        label: Text(label, style: const TextStyle(fontSize: 16)),
        style: ElevatedButton.styleFrom(
          backgroundColor: color,
          foregroundColor: Colors.white,
          elevation: 2,
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
        ),
      ),
    );
  }
}