309 lines
10 KiB
JavaScript
309 lines
10 KiB
JavaScript
// Module de simulation CTI (Computer Telephony Integration)
|
|
// Ce module simule l'intégration téléphonique pour les tests
|
|
|
|
class CTISimulator {
|
|
constructor() {
|
|
this.isRunning = false;
|
|
this.autoCallInterval = null;
|
|
this.callHistory = [];
|
|
}
|
|
|
|
// Démarrer la simulation automatique d'appels
|
|
startAutoSimulation(intervalSeconds = 60) {
|
|
if (this.isRunning) return;
|
|
|
|
this.isRunning = true;
|
|
console.log(`Simulation CTI démarrée - Appels toutes les ${intervalSeconds} secondes`);
|
|
|
|
// Premier appel après 10 secondes
|
|
setTimeout(() => {
|
|
this.generateRandomCall();
|
|
}, 10000);
|
|
|
|
// Puis appels réguliers
|
|
this.autoCallInterval = setInterval(() => {
|
|
if (Math.random() > 0.3) { // 70% de chance d'avoir un appel
|
|
this.generateRandomCall();
|
|
}
|
|
}, intervalSeconds * 1000);
|
|
}
|
|
|
|
// Arrêter la simulation
|
|
stopAutoSimulation() {
|
|
if (this.autoCallInterval) {
|
|
clearInterval(this.autoCallInterval);
|
|
this.autoCallInterval = null;
|
|
}
|
|
this.isRunning = false;
|
|
console.log('Simulation CTI arrêtée');
|
|
}
|
|
|
|
// Générer un appel aléatoire
|
|
async generateRandomCall() {
|
|
const config = await ipcRenderer.invoke('get-config');
|
|
const simulatedCalls = config.cti.appelSimules;
|
|
|
|
if (!simulatedCalls || simulatedCalls.length === 0) return;
|
|
|
|
// Sélectionner un appel au hasard
|
|
const randomCall = simulatedCalls[Math.floor(Math.random() * simulatedCalls.length)];
|
|
|
|
// Vérifier que l'agent a accès à ce centre
|
|
const currentAgent = await ipcRenderer.invoke('get-current-agent');
|
|
if (!currentAgent || !currentAgent.agent.centresAssignes.includes(randomCall.centreId)) {
|
|
// Essayer avec un autre appel
|
|
const validCalls = simulatedCalls.filter(call =>
|
|
currentAgent.agent.centresAssignes.includes(call.centreId)
|
|
);
|
|
|
|
if (validCalls.length > 0) {
|
|
const validCall = validCalls[Math.floor(Math.random() * validCalls.length)];
|
|
this.triggerIncomingCall(validCall);
|
|
}
|
|
} else {
|
|
this.triggerIncomingCall(randomCall);
|
|
}
|
|
}
|
|
|
|
// Déclencher un appel entrant
|
|
triggerIncomingCall(callData) {
|
|
console.log('Appel entrant simulé:', callData);
|
|
|
|
// Ajouter des métadonnées
|
|
const enrichedCall = {
|
|
...callData,
|
|
id: this.generateCallId(),
|
|
timestamp: new Date().toISOString(),
|
|
duration: 0,
|
|
status: 'ringing'
|
|
};
|
|
|
|
// Ajouter à l'historique
|
|
this.callHistory.push(enrichedCall);
|
|
|
|
// Déclencher l'événement
|
|
ipcRenderer.invoke('simulate-call', enrichedCall);
|
|
}
|
|
|
|
// Générer un ID unique pour l'appel
|
|
generateCallId() {
|
|
return `CALL-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
}
|
|
|
|
// Obtenir les statistiques des appels
|
|
getCallStats() {
|
|
const now = new Date();
|
|
const todayStart = new Date(now.setHours(0, 0, 0, 0));
|
|
|
|
const todayCalls = this.callHistory.filter(call =>
|
|
new Date(call.timestamp) >= todayStart
|
|
);
|
|
|
|
return {
|
|
total: this.callHistory.length,
|
|
today: todayCalls.length,
|
|
answered: todayCalls.filter(c => c.status === 'answered').length,
|
|
missed: todayCalls.filter(c => c.status === 'missed').length,
|
|
average_duration: this.calculateAverageDuration(todayCalls)
|
|
};
|
|
}
|
|
|
|
// Calculer la durée moyenne des appels
|
|
calculateAverageDuration(calls) {
|
|
const answered = calls.filter(c => c.duration > 0);
|
|
if (answered.length === 0) return 0;
|
|
|
|
const total = answered.reduce((sum, call) => sum + call.duration, 0);
|
|
return Math.round(total / answered.length);
|
|
}
|
|
|
|
// Simuler différents scénarios d'appels
|
|
simulateScenarios() {
|
|
const scenarios = [
|
|
{
|
|
name: 'Appel urgent',
|
|
setup: () => {
|
|
this.triggerIncomingCall({
|
|
numero: '+33699887766',
|
|
nom: 'URGENT - Marie LAMBERT',
|
|
centreId: 'centre1',
|
|
priority: 'high',
|
|
motif: 'Consultation urgente cardiologie'
|
|
});
|
|
}
|
|
},
|
|
{
|
|
name: 'Patient régulier',
|
|
setup: () => {
|
|
this.triggerIncomingCall({
|
|
numero: '+33612345678',
|
|
nom: 'Jean DUPUIS (Patient régulier)',
|
|
centreId: 'centre2',
|
|
priority: 'normal',
|
|
motif: 'Suivi mensuel',
|
|
lastVisit: '2024-11-15'
|
|
});
|
|
}
|
|
},
|
|
{
|
|
name: 'Nouveau patient',
|
|
setup: () => {
|
|
this.triggerIncomingCall({
|
|
numero: '+33755443322',
|
|
nom: 'Sophie MARTIN',
|
|
centreId: 'centre3',
|
|
priority: 'normal',
|
|
motif: 'Première consultation',
|
|
isNew: true
|
|
});
|
|
}
|
|
},
|
|
{
|
|
name: 'Appel pour résultats',
|
|
setup: () => {
|
|
this.triggerIncomingCall({
|
|
numero: '+33688776655',
|
|
nom: 'Paul BERNARD',
|
|
centreId: 'centre4',
|
|
priority: 'low',
|
|
motif: 'Demande résultats radiologie',
|
|
examDate: '2024-12-20'
|
|
});
|
|
}
|
|
}
|
|
];
|
|
|
|
return scenarios;
|
|
}
|
|
|
|
// Interface de test pour le développement
|
|
showTestPanel() {
|
|
const testPanel = document.createElement('div');
|
|
testPanel.id = 'cti-test-panel';
|
|
testPanel.className = 'cti-test-panel';
|
|
testPanel.innerHTML = `
|
|
<h3>Panneau de test CTI</h3>
|
|
<div class="test-controls">
|
|
<button onclick="ctiSimulator.generateRandomCall()">Appel aléatoire</button>
|
|
<button onclick="ctiSimulator.startAutoSimulation(30)">Démarrer auto (30s)</button>
|
|
<button onclick="ctiSimulator.stopAutoSimulation()">Arrêter auto</button>
|
|
</div>
|
|
<div class="test-scenarios">
|
|
<h4>Scénarios</h4>
|
|
${this.simulateScenarios().map(s =>
|
|
`<button onclick="ctiSimulator.runScenario('${s.name}')">${s.name}</button>`
|
|
).join('')}
|
|
</div>
|
|
<div class="test-stats">
|
|
<h4>Statistiques</h4>
|
|
<div id="cti-stats"></div>
|
|
</div>
|
|
`;
|
|
|
|
// Ajouter les styles
|
|
if (!document.getElementById('cti-test-styles')) {
|
|
const styles = document.createElement('style');
|
|
styles.id = 'cti-test-styles';
|
|
styles.innerHTML = `
|
|
.cti-test-panel {
|
|
position: fixed;
|
|
right: 20px;
|
|
bottom: 20px;
|
|
width: 300px;
|
|
background: white;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8px;
|
|
padding: 15px;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
z-index: 9999;
|
|
}
|
|
.cti-test-panel h3 {
|
|
margin-bottom: 10px;
|
|
color: #333;
|
|
font-size: 16px;
|
|
}
|
|
.cti-test-panel h4 {
|
|
margin: 10px 0 5px 0;
|
|
color: #666;
|
|
font-size: 14px;
|
|
}
|
|
.test-controls button,
|
|
.test-scenarios button {
|
|
margin: 5px;
|
|
padding: 5px 10px;
|
|
background: #667eea;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
}
|
|
.test-controls button:hover,
|
|
.test-scenarios button:hover {
|
|
background: #5a6fd8;
|
|
}
|
|
#cti-stats {
|
|
font-size: 12px;
|
|
color: #666;
|
|
}
|
|
`;
|
|
document.head.appendChild(styles);
|
|
}
|
|
|
|
document.body.appendChild(testPanel);
|
|
this.updateStats();
|
|
}
|
|
|
|
// Exécuter un scénario
|
|
runScenario(name) {
|
|
const scenario = this.simulateScenarios().find(s => s.name === name);
|
|
if (scenario) {
|
|
scenario.setup();
|
|
}
|
|
}
|
|
|
|
// Mettre à jour les statistiques
|
|
updateStats() {
|
|
const stats = this.getCallStats();
|
|
const statsDiv = document.getElementById('cti-stats');
|
|
if (statsDiv) {
|
|
statsDiv.innerHTML = `
|
|
<div>Total: ${stats.total} appels</div>
|
|
<div>Aujourd'hui: ${stats.today}</div>
|
|
<div>Répondus: ${stats.answered}</div>
|
|
<div>Manqués: ${stats.missed}</div>
|
|
<div>Durée moy: ${stats.average_duration}s</div>
|
|
`;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Créer une instance globale
|
|
const ctiSimulator = new CTISimulator();
|
|
|
|
// Exposer pour les tests en développement
|
|
if (process.env.NODE_ENV === 'development') {
|
|
window.ctiSimulator = ctiSimulator;
|
|
// Afficher le panneau de test après connexion
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
setTimeout(() => {
|
|
const mainPage = document.getElementById('mainPage');
|
|
if (mainPage && mainPage.classList.contains('active')) {
|
|
ctiSimulator.showTestPanel();
|
|
}
|
|
}, 2000);
|
|
});
|
|
}
|
|
|
|
// Démarrer la simulation automatique après connexion (optionnel)
|
|
ipcRenderer.on('agent-logged-in', () => {
|
|
// Démarrer la simulation après 5 secondes
|
|
setTimeout(() => {
|
|
ctiSimulator.startAutoSimulation(90); // Un appel toutes les 90 secondes
|
|
}, 5000);
|
|
});
|
|
|
|
// Arrêter la simulation à la déconnexion
|
|
ipcRenderer.on('agent-logged-out', () => {
|
|
ctiSimulator.stopAutoSimulation();
|
|
}); |