@developpement/tp-chatbot-widget 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/chatbot.css +0 -1
- package/src/chatbot.js +78 -14
package/package.json
CHANGED
package/src/chatbot.css
CHANGED
package/src/chatbot.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const CLIENT_THEMES = {
|
|
5
|
-
flix: { primary: '#7b1fa2', name: 'Flix Corporate' },
|
|
6
|
-
sncf: { primary: '#1a6b5a', name: 'SNCF' },
|
|
5
|
+
flix: { primary: '#7b1fa2', name: 'Flix Corporate', position: 'left' },
|
|
6
|
+
sncf: { primary: '#1a6b5a', name: 'SNCF', position: 'right' },
|
|
7
7
|
};
|
|
8
|
-
const DEFAULT_THEME = { primary: '#7b1fa2', name: 'Support' };
|
|
8
|
+
const DEFAULT_THEME = { primary: '#7b1fa2', name: 'Support', position: 'right' };
|
|
9
9
|
|
|
10
10
|
function getClientTheme(client_id) {
|
|
11
11
|
return CLIENT_THEMES[client_id] || DEFAULT_THEME;
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
this.view = 'list';
|
|
101
101
|
|
|
102
102
|
this.render();
|
|
103
|
-
this.applyTheme();
|
|
103
|
+
this.applyTheme();
|
|
104
104
|
this.attachEvents();
|
|
105
105
|
this._initialized = true;
|
|
106
106
|
|
|
@@ -109,7 +109,6 @@
|
|
|
109
109
|
this.user_id = this.user_info?.user_id;
|
|
110
110
|
this.showConversationList();
|
|
111
111
|
} else {
|
|
112
|
-
// Attend 500ms que le framework passe le token
|
|
113
112
|
setTimeout(() => {
|
|
114
113
|
const token = this.getAttribute('access-token');
|
|
115
114
|
if (token) {
|
|
@@ -166,6 +165,28 @@
|
|
|
166
165
|
.tp-conv-new-btn { background: linear-gradient(135deg, ${color}, ${dark}) !important; }
|
|
167
166
|
`;
|
|
168
167
|
document.head.appendChild(style);
|
|
168
|
+
|
|
169
|
+
const position = getClientTheme(this.client_id).position || 'right';
|
|
170
|
+
|
|
171
|
+
const host = this.querySelector('.tp-chatbot-host');
|
|
172
|
+
if (host) {
|
|
173
|
+
host.style.width = '360px';
|
|
174
|
+
host.style.left = position === 'left' ? '24px' : 'auto';
|
|
175
|
+
host.style.right = position === 'left' ? 'auto' : '24px';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const bubble = this.querySelector('.tp-chatbot-bubble');
|
|
179
|
+
if (bubble) {
|
|
180
|
+
bubble.style.marginLeft = position === 'left' ? '0' : 'auto';
|
|
181
|
+
bubble.style.marginRight = position === 'left' ? 'auto' : '0';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const win = this.querySelector('.tp-chatbot-window');
|
|
185
|
+
if (win) {
|
|
186
|
+
win.style.left = '0';
|
|
187
|
+
win.style.right = 'auto';
|
|
188
|
+
win.style.transformOrigin = position === 'left' ? 'bottom left' : 'bottom right';
|
|
189
|
+
}
|
|
169
190
|
}
|
|
170
191
|
|
|
171
192
|
// ─── Render ───────────────────────────────────────────────────────────────
|
|
@@ -399,7 +420,7 @@
|
|
|
399
420
|
this.last_message_count = conv.messages.length;
|
|
400
421
|
|
|
401
422
|
if (conv.status === 'closed') {
|
|
402
|
-
this.showClosed();
|
|
423
|
+
this.showClosed(conv.csat || null);
|
|
403
424
|
return;
|
|
404
425
|
}
|
|
405
426
|
|
|
@@ -453,7 +474,7 @@
|
|
|
453
474
|
if (input_bar) input_bar.style.display = 'flex';
|
|
454
475
|
|
|
455
476
|
const agent_bar = this.querySelector('#tp-agent-bar');
|
|
456
|
-
if (agent_bar) agent_bar.style.display = '
|
|
477
|
+
if (agent_bar) agent_bar.style.display = 'none';
|
|
457
478
|
|
|
458
479
|
this.conversation_id = await this.createConversation();
|
|
459
480
|
this.addMessage('assistant', `Bonjour ${this.user_info?.first_name || ''} ! Comment puis-je vous aider ?`);
|
|
@@ -583,7 +604,7 @@
|
|
|
583
604
|
if (typing) typing.remove();
|
|
584
605
|
}
|
|
585
606
|
|
|
586
|
-
showClosed() {
|
|
607
|
+
showClosed(existing_csat = null) {
|
|
587
608
|
this.is_closed = true;
|
|
588
609
|
if (this.polling_interval) {
|
|
589
610
|
clearInterval(this.polling_interval);
|
|
@@ -603,16 +624,30 @@
|
|
|
603
624
|
if (close_bar) close_bar.style.display = 'none';
|
|
604
625
|
|
|
605
626
|
const container = this.querySelector('#tp-messages');
|
|
606
|
-
|
|
627
|
+
|
|
628
|
+
const existing_banner = this.querySelector('#tp-closed-banner');
|
|
629
|
+
if (existing_banner) {
|
|
630
|
+
if (existing_banner.querySelector('#tp-csat-block')) return; // déjà complet
|
|
631
|
+
existing_banner.remove(); // incomplet, on recrée
|
|
632
|
+
}
|
|
607
633
|
|
|
608
634
|
const color = this.getThemeColor();
|
|
609
635
|
const dark = this.shadeColor(color, -20);
|
|
610
636
|
|
|
637
|
+
const csat_html = existing_csat
|
|
638
|
+
? `<div style="font-size:13px;color:#888;margin-bottom:14px;">${existing_csat === 'positive' ? '👍 Merci pour votre retour !' : '👎 Merci, nous allons nous améliorer.'}</div>`
|
|
639
|
+
: `<div style="font-size:12px;color:#888;margin-bottom:10px;">Cette conversation vous a-t-elle été utile ?</div>
|
|
640
|
+
<div style="display:flex;gap:10px;justify-content:center;margin-bottom:14px;">
|
|
641
|
+
<button id="tp-csat-positive" style="padding:8px 20px;border-radius:8px;border:1.5px solid #22c55e;background:white;color:#22c55e;font-size:18px;cursor:pointer;font-weight:700;">👍</button>
|
|
642
|
+
<button id="tp-csat-negative" style="padding:8px 20px;border-radius:8px;border:1.5px solid #ef4444;background:white;color:#ef4444;font-size:18px;cursor:pointer;font-weight:700;">👎</button>
|
|
643
|
+
</div>`;
|
|
644
|
+
|
|
611
645
|
const banner = document.createElement('div');
|
|
612
646
|
banner.id = 'tp-closed-banner';
|
|
613
647
|
banner.innerHTML = `
|
|
614
|
-
<div style="margin:16px;padding:16px;background:#
|
|
615
|
-
<div style="font-size:13px;color:#
|
|
648
|
+
<div style="margin:16px;padding:16px;background:#f9f5ff;border:1px solid #ede8f5;border-radius:12px;text-align:center;">
|
|
649
|
+
<div style="font-size:13px;color:#1a1a2e;font-weight:600;margin-bottom:8px;">✅ Conversation clôturée</div>
|
|
650
|
+
<div id="tp-csat-block">${csat_html}</div>
|
|
616
651
|
<button id="tp-new-conversation" style="padding:10px 20px;background:linear-gradient(135deg,${color},${dark});color:white;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;margin-bottom:8px;width:100%;">
|
|
617
652
|
💬 Nouvelle conversation
|
|
618
653
|
</button>
|
|
@@ -624,6 +659,26 @@
|
|
|
624
659
|
container.appendChild(banner);
|
|
625
660
|
container.scrollTop = container.scrollHeight;
|
|
626
661
|
|
|
662
|
+
if (!existing_csat) {
|
|
663
|
+
const submit_csat = async rating => {
|
|
664
|
+
const csat_block = this.querySelector('#tp-csat-block');
|
|
665
|
+
if (!csat_block) return;
|
|
666
|
+
try {
|
|
667
|
+
await fetch(`${this.api_url}/chat/conversations/${this.conversation_id}/csat`, {
|
|
668
|
+
method: 'POST',
|
|
669
|
+
headers: this.getHeaders(true),
|
|
670
|
+
body: JSON.stringify({ user_id: this.user_id, rating }),
|
|
671
|
+
});
|
|
672
|
+
} catch (e) {
|
|
673
|
+
console.error('CSAT error:', e);
|
|
674
|
+
}
|
|
675
|
+
csat_block.innerHTML = `<div style="font-size:13px;color:#888;margin-bottom:14px;">${rating === 'positive' ? '👍 Merci pour votre retour !' : '👎 Merci, nous allons nous améliorer.'}</div>`;
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
this.querySelector('#tp-csat-positive').addEventListener('click', () => submit_csat('positive'));
|
|
679
|
+
this.querySelector('#tp-csat-negative').addEventListener('click', () => submit_csat('negative'));
|
|
680
|
+
}
|
|
681
|
+
|
|
627
682
|
this.querySelector('#tp-new-conversation').addEventListener('click', () => this.startNewConversation());
|
|
628
683
|
this.querySelector('#tp-back-to-list').addEventListener('click', () => this.showConversationList());
|
|
629
684
|
}
|
|
@@ -663,20 +718,29 @@
|
|
|
663
718
|
this.hideTyping();
|
|
664
719
|
|
|
665
720
|
if (response.status === 429) {
|
|
666
|
-
this.addMessage('system',
|
|
667
|
-
const input_bar = this.querySelector('#tp-chatbot-input-bar');
|
|
668
|
-
if (input_bar) input_bar.style.display = 'none';
|
|
721
|
+
this.addMessage('system', data.error?.message || 'Trop de messages. Veuillez patienter avant de réessayer.');
|
|
669
722
|
this.is_loading = false;
|
|
670
723
|
return;
|
|
671
724
|
}
|
|
672
725
|
|
|
673
726
|
this.agent_mode = data.result.agent_mode;
|
|
727
|
+
const source = data.result.source || null;
|
|
728
|
+
|
|
674
729
|
const subtitle = this.querySelector('#tp-subtitle');
|
|
675
730
|
if (subtitle) subtitle.textContent = this.agent_mode ? '👤 Agent humain' : '🤖 Assistant virtuel';
|
|
676
731
|
|
|
677
732
|
if (data.result.reply) {
|
|
678
733
|
this.addMessage(this.agent_mode ? 'agent' : 'assistant', data.result.reply);
|
|
679
734
|
}
|
|
735
|
+
|
|
736
|
+
// Afficher bouton agent si fallback ou ≥ 3 messages user
|
|
737
|
+
const user_msg_count = this.messages.filter(m => m.role === 'user').length;
|
|
738
|
+
const agent_bar = this.querySelector('#tp-agent-bar');
|
|
739
|
+
if (agent_bar && !this.agent_requested && !this.agent_mode) {
|
|
740
|
+
if (source === 'fallback' || user_msg_count >= 5) {
|
|
741
|
+
agent_bar.style.display = 'block';
|
|
742
|
+
}
|
|
743
|
+
}
|
|
680
744
|
} catch {
|
|
681
745
|
this.hideTyping();
|
|
682
746
|
this.addMessage('assistant', 'Une erreur est survenue. Veuillez réessayer.');
|