335 lines
9.1 KiB
TypeScript
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,
|
|
};
|
|
};
|