Files
unionflow-server-impl-quarkus/unionflow-mobile-apps/src/contexts/WavePaymentContext.tsx
2025-08-20 21:00:35 +00:00

335 lines
9.1 KiB
TypeScript

import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import NetInfo from '@react-native-community/netinfo';
import {
WavePaymentService,
WavePaymentRequest,
WavePaymentResult,
WaveTransactionStatus
} from '../services/WavePaymentService';
import { AnalyticsService } from '../services/AnalyticsService';
/**
* Contexte Wave Payment pour la gestion globale des paiements Wave Money
*
* Ce contexte fournit :
* - État global des paiements Wave
* - Gestion de la connectivité et synchronisation
* - Cache des transactions récentes
* - Notifications de statut en temps réel
*
* @author Lions Dev Team
* @version 2.0.0
* @since 2025-01-16
*/
interface WavePaymentContextType {
// État des paiements
isLoading: boolean;
currentTransaction: WavePaymentResult | null;
recentTransactions: WavePaymentResult[];
// Connectivité
isOnline: boolean;
pendingPaymentsCount: number;
// Actions
initiatePayment: (request: WavePaymentRequest) => Promise<WavePaymentResult>;
checkTransactionStatus: (transactionId: string) => Promise<WaveTransactionStatus>;
refreshTransactions: () => Promise<void>;
syncPendingPayments: () => Promise<void>;
clearCurrentTransaction: () => void;
// Utilitaires
calculateFees: (amount: string) => Promise<{ base: string; fees: string; total: string }>;
getPaymentHistory: () => Promise<WavePaymentResult[]>;
}
const WavePaymentContext = createContext<WavePaymentContextType | undefined>(undefined);
interface WavePaymentProviderProps {
children: ReactNode;
}
export const WavePaymentProvider: React.FC<WavePaymentProviderProps> = ({ children }) => {
const [isLoading, setIsLoading] = useState(false);
const [currentTransaction, setCurrentTransaction] = useState<WavePaymentResult | null>(null);
const [recentTransactions, setRecentTransactions] = useState<WavePaymentResult[]>([]);
const [isOnline, setIsOnline] = useState(true);
const [pendingPaymentsCount, setPendingPaymentsCount] = useState(0);
useEffect(() => {
initializeContext();
setupNetworkListener();
}, []);
/**
* Initialise le contexte avec les données sauvegardées
*/
const initializeContext = async () => {
try {
// Charger l'historique des paiements
const history = await WavePaymentService.getPaymentHistory();
setRecentTransactions(history.slice(0, 10)); // 10 plus récents
// Compter les paiements en attente
await updatePendingPaymentsCount();
} catch (error) {
console.error('Erreur initialisation contexte Wave:', error);
}
};
/**
* Configure l'écoute de la connectivité réseau
*/
const setupNetworkListener = () => {
const unsubscribe = NetInfo.addEventListener(state => {
const wasOffline = !isOnline;
const isNowOnline = state.isConnected ?? false;
setIsOnline(isNowOnline);
// Si on revient en ligne, synchroniser les paiements en attente
if (wasOffline && isNowOnline) {
console.log('Connexion rétablie - Synchronisation des paiements Wave');
syncPendingPayments();
}
});
return unsubscribe;
};
/**
* Met à jour le nombre de paiements en attente
*/
const updatePendingPaymentsCount = async () => {
try {
const pendingPayments = await WavePaymentService.getPendingPayments();
setPendingPaymentsCount(pendingPayments.length);
} catch (error) {
console.error('Erreur mise à jour paiements en attente:', error);
}
};
/**
* Initie un paiement Wave Money
*/
const initiatePayment = async (request: WavePaymentRequest): Promise<WavePaymentResult> => {
setIsLoading(true);
setCurrentTransaction(null);
try {
const result = await WavePaymentService.initiatePayment(request);
setCurrentTransaction(result);
if (result.success) {
// Ajouter à l'historique récent
setRecentTransactions(prev => [result, ...prev.slice(0, 9)]);
// Analytics
AnalyticsService.trackEvent('wave_payment_context_success', {
type: request.type,
amount: request.amount,
transactionId: result.transactionId,
});
} else {
// Si échec à cause de la connectivité, mettre à jour le compteur
if (!isOnline) {
await updatePendingPaymentsCount();
}
AnalyticsService.trackEvent('wave_payment_context_failure', {
type: request.type,
amount: request.amount,
error: result.error,
});
}
return result;
} catch (error) {
console.error('Erreur contexte paiement Wave:', error);
const errorResult: WavePaymentResult = {
success: false,
error: 'Erreur inattendue lors du paiement',
};
setCurrentTransaction(errorResult);
return errorResult;
} finally {
setIsLoading(false);
}
};
/**
* Vérifie le statut d'une transaction
*/
const checkTransactionStatus = async (transactionId: string): Promise<WaveTransactionStatus> => {
try {
const status = await WavePaymentService.checkTransactionStatus(transactionId);
// Mettre à jour la transaction dans l'historique si nécessaire
setRecentTransactions(prev =>
prev.map(transaction =>
transaction.transactionId === transactionId
? { ...transaction, status: status.status as any }
: transaction
)
);
return status;
} catch (error) {
console.error('Erreur vérification statut:', error);
throw error;
}
};
/**
* Actualise la liste des transactions
*/
const refreshTransactions = async () => {
try {
const history = await WavePaymentService.getPaymentHistory();
setRecentTransactions(history.slice(0, 10));
await updatePendingPaymentsCount();
} catch (error) {
console.error('Erreur actualisation transactions:', error);
}
};
/**
* Synchronise les paiements en attente
*/
const syncPendingPayments = async () => {
if (!isOnline) {
console.log('Hors ligne - Synchronisation reportée');
return;
}
try {
await WavePaymentService.syncPendingPayments();
await updatePendingPaymentsCount();
await refreshTransactions();
AnalyticsService.trackEvent('wave_payments_synced', {
pendingCount: pendingPaymentsCount,
});
} catch (error) {
console.error('Erreur synchronisation paiements:', error);
}
};
/**
* Efface la transaction courante
*/
const clearCurrentTransaction = () => {
setCurrentTransaction(null);
};
/**
* Calcule les frais Wave Money
*/
const calculateFees = async (amount: string) => {
try {
return await WavePaymentService.calculateFees(amount);
} catch (error) {
console.error('Erreur calcul frais contexte:', error);
throw error;
}
};
/**
* Retourne l'historique complet des paiements
*/
const getPaymentHistory = async (): Promise<WavePaymentResult[]> => {
try {
return await WavePaymentService.getPaymentHistory();
} catch (error) {
console.error('Erreur récupération historique:', error);
return [];
}
};
const contextValue: WavePaymentContextType = {
// État
isLoading,
currentTransaction,
recentTransactions,
isOnline,
pendingPaymentsCount,
// Actions
initiatePayment,
checkTransactionStatus,
refreshTransactions,
syncPendingPayments,
clearCurrentTransaction,
// Utilitaires
calculateFees,
getPaymentHistory,
};
return (
<WavePaymentContext.Provider value={contextValue}>
{children}
</WavePaymentContext.Provider>
);
};
/**
* Hook pour utiliser le contexte Wave Payment
*/
export const useWavePayment = (): WavePaymentContextType => {
const context = useContext(WavePaymentContext);
if (context === undefined) {
throw new Error('useWavePayment doit être utilisé dans un WavePaymentProvider');
}
return context;
};
/**
* Hook pour vérifier si Wave Money est disponible
*/
export const useWaveAvailability = () => {
const { isOnline } = useWavePayment();
return {
isWaveAvailable: isOnline, // Simplification - en réalité, vérifier aussi la config
reason: isOnline ? null : 'Connexion internet requise',
};
};
/**
* Hook pour les statistiques de paiement Wave
*/
export const useWaveStats = () => {
const { recentTransactions, pendingPaymentsCount } = useWavePayment();
const successfulPayments = recentTransactions.filter(t => t.success).length;
const failedPayments = recentTransactions.filter(t => !t.success).length;
const totalAmount = recentTransactions
.filter(t => t.success)
.reduce((sum, t) => {
// Extraire le montant de la transaction (simplification)
return sum + 0; // À implémenter selon le format des données
}, 0);
return {
successfulPayments,
failedPayments,
pendingPaymentsCount,
totalAmount,
successRate: recentTransactions.length > 0
? (successfulPayments / recentTransactions.length) * 100
: 0,
};
};