@developpement/tp-chatbot-widget 0.0.1 → 0.0.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/chatbot.js +56 -63
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@developpement/tp-chatbot-widget",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Chatbot widget for TravelPlanet / Makitizy",
5
5
  "main": "src/chatbot.js",
6
6
  "files": [
package/src/chatbot.js CHANGED
@@ -32,7 +32,27 @@
32
32
  this.polling_interval = null;
33
33
  this.user_info = null;
34
34
  this.is_closed = false;
35
- this.view = 'list'; // 'list' | 'chat'
35
+ this.view = 'list';
36
+ this._initialized = false;
37
+ }
38
+
39
+ static get observedAttributes() {
40
+ return ['access-token'];
41
+ }
42
+
43
+ attributeChangedCallback(name, old_val, new_val) {
44
+ if (name === 'access-token' && new_val && new_val !== old_val && this._initialized) {
45
+ this.access_token = new_val;
46
+ this.user_info = extractUserInfo(new_val);
47
+ this.user_id = this.user_info?.user_id;
48
+ this.applyTheme();
49
+
50
+ const guest_form = this.querySelector('#tp-guest-form');
51
+ if (guest_form) {
52
+ guest_form.remove();
53
+ this.showConversationList();
54
+ }
55
+ }
36
56
  }
37
57
 
38
58
  connectedCallback() {
@@ -48,14 +68,27 @@
48
68
 
49
69
  this.render();
50
70
  this.attachEvents();
71
+ this._initialized = true;
51
72
 
52
73
  if (this.access_token) {
53
74
  this.user_info = extractUserInfo(this.access_token);
54
- this.user_id = this.user_info.user_id;
75
+ this.user_id = this.user_info?.user_id;
55
76
  this.applyTheme();
56
77
  this.showConversationList();
57
78
  } else {
58
- this.showGuestForm();
79
+ // Attend 500ms que le framework passe le token
80
+ setTimeout(() => {
81
+ const token = this.getAttribute('access-token');
82
+ if (token) {
83
+ this.access_token = token;
84
+ this.user_info = extractUserInfo(token);
85
+ this.user_id = this.user_info?.user_id;
86
+ this.applyTheme();
87
+ this.showConversationList();
88
+ } else {
89
+ this.showGuestForm();
90
+ }
91
+ }, 500);
59
92
  }
60
93
  }
61
94
 
@@ -138,10 +171,7 @@
138
171
  this.querySelector('#tp-agent-btn').addEventListener('click', () => this.requestAgent());
139
172
  this.querySelector('#tp-back-btn').addEventListener('click', () => this.showConversationList());
140
173
  this.querySelector('#tp-input').addEventListener('keydown', e => {
141
- if (e.key === 'Enter' && !e.shiftKey) {
142
- e.preventDefault();
143
- this.sendMessage();
144
- }
174
+ if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); this.sendMessage(); }
145
175
  });
146
176
  }
147
177
 
@@ -149,13 +179,8 @@
149
179
  this.is_open = !this.is_open;
150
180
  const window_el = this.querySelector('#tp-window');
151
181
  const bubble = this.querySelector('#tp-bubble');
152
- if (this.is_open) {
153
- window_el.classList.add('open');
154
- bubble.textContent = '✕';
155
- } else {
156
- window_el.classList.remove('open');
157
- bubble.textContent = '💬';
158
- }
182
+ if (this.is_open) { window_el.classList.add('open'); bubble.textContent = '✕'; }
183
+ else { window_el.classList.remove('open'); bubble.textContent = '💬'; }
159
184
  }
160
185
 
161
186
  getHeaders(content_type = false) {
@@ -180,10 +205,7 @@
180
205
  async showConversationList() {
181
206
  this.view = 'list';
182
207
 
183
- if (this.polling_interval) {
184
- clearInterval(this.polling_interval);
185
- this.polling_interval = null;
186
- }
208
+ if (this.polling_interval) { clearInterval(this.polling_interval); this.polling_interval = null; }
187
209
 
188
210
  const subtitle = this.querySelector('#tp-subtitle');
189
211
  if (subtitle) subtitle.textContent = '🤖 Assistant virtuel';
@@ -211,18 +233,14 @@
211
233
 
212
234
  container.innerHTML = '';
213
235
 
214
- // Header list
215
236
  const header_el = document.createElement('div');
216
237
  header_el.style.cssText = 'padding:16px;border-bottom:1px solid #ede8f5;';
217
238
  header_el.innerHTML = `
218
- <div style="font-size:13px;font-weight:700;color:#1a1a2e;margin-bottom:4px;">
219
- Bonjour ${this.user_info?.first_name || ''} 👋
220
- </div>
239
+ <div style="font-size:13px;font-weight:700;color:#1a1a2e;margin-bottom:4px;">Bonjour ${this.user_info?.first_name || ''} 👋</div>
221
240
  <div style="font-size:12px;color:#aaa;">Vos conversations récentes</div>
222
241
  `;
223
242
  container.appendChild(header_el);
224
243
 
225
- // Conversation items
226
244
  if (conversations.length === 0) {
227
245
  const empty = document.createElement('div');
228
246
  empty.style.cssText = 'padding:24px 16px;text-align:center;color:#aaa;font-size:13px;';
@@ -235,21 +253,10 @@
235
253
  item.style.cssText = 'padding:14px 16px;border-bottom:1px solid #f5f0fa;cursor:pointer;transition:background 0.15s;';
236
254
 
237
255
  const is_closed = conv.status === 'closed';
238
- const status_label = is_closed
239
- ? '✅ Fermée'
240
- : conv.status === 'agent'
241
- ? '👤 Agent'
242
- : conv.status === 'waiting_agent'
243
- ? '⏳ En attente'
244
- : '🤖 Bot';
256
+ const status_label = is_closed ? '✅ Fermée' : conv.status === 'agent' ? '👤 Agent' : conv.status === 'waiting_agent' ? '⏳ En attente' : '🤖 Bot';
245
257
  const status_color = is_closed ? '#9ca3af' : conv.status === 'waiting_agent' ? '#f59e0b' : color;
246
258
 
247
- const date = new Date(conv.updated_at).toLocaleDateString('fr-FR', {
248
- day: '2-digit',
249
- month: '2-digit',
250
- hour: '2-digit',
251
- minute: '2-digit',
252
- });
259
+ const date = new Date(conv.updated_at).toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });
253
260
 
254
261
  item.innerHTML = `
255
262
  <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;">
@@ -264,7 +271,6 @@
264
271
  });
265
272
  }
266
273
 
267
- // New conversation button
268
274
  const new_btn_wrap = document.createElement('div');
269
275
  new_btn_wrap.style.cssText = 'padding:16px;';
270
276
  new_btn_wrap.innerHTML = `
@@ -274,6 +280,7 @@
274
280
  `;
275
281
  new_btn_wrap.querySelector('button').addEventListener('click', () => this.startNewConversation());
276
282
  container.appendChild(new_btn_wrap);
283
+
277
284
  } catch (e) {
278
285
  console.error('showConversationList error:', e);
279
286
  container.innerHTML = '<div style="padding:16px;text-align:center;color:#ef4444;font-size:13px;">Erreur de chargement.</div>';
@@ -313,10 +320,7 @@
313
320
 
314
321
  this.last_message_count = conv.messages.length;
315
322
 
316
- if (conv.status === 'closed') {
317
- this.showClosed();
318
- return;
319
- }
323
+ if (conv.status === 'closed') { this.showClosed(); return; }
320
324
 
321
325
  if (conv.status === 'agent') {
322
326
  this.agent_mode = true;
@@ -445,18 +449,16 @@
445
449
  const container = this.querySelector('#tp-messages');
446
450
 
447
451
  const role_label =
448
- role === 'user'
449
- ? `👤 ${this.user_info?.first_name || 'Vous'}`
450
- : role === 'agent'
451
- ? '👨‍💼 Agent'
452
- : role === 'system'
453
- ? 'ℹ️ Info'
454
- : '🤖 Assistant';
452
+ role === 'user' ? `👤 ${this.user_info?.first_name || 'Vous'}`
453
+ : role === 'agent' ? '👨‍💼 Agent'
454
+ : role === 'system' ? 'ℹ️ Info'
455
+ : '🤖 Assistant';
455
456
 
456
457
  const msg_el = document.createElement('div');
457
458
  msg_el.className = `tp-chatbot-message ${role}`;
458
- const rendered_content =
459
- role === 'assistant' || role === 'agent' ? (typeof marked !== 'undefined' ? marked.parse(content) : content) : content;
459
+ const rendered_content = (role === 'assistant' || role === 'agent')
460
+ ? (typeof marked !== 'undefined' ? marked.parse(content) : content)
461
+ : content;
460
462
 
461
463
  msg_el.innerHTML = `
462
464
  <div class="tp-chatbot-bubble-msg">
@@ -486,10 +488,7 @@
486
488
  showClosed() {
487
489
  this.is_closed = true;
488
490
 
489
- if (this.polling_interval) {
490
- clearInterval(this.polling_interval);
491
- this.polling_interval = null;
492
- }
491
+ if (this.polling_interval) { clearInterval(this.polling_interval); this.polling_interval = null; }
493
492
 
494
493
  const subtitle = this.querySelector('#tp-subtitle');
495
494
  if (subtitle) subtitle.textContent = '✅ Conversation terminée';
@@ -536,10 +535,7 @@
536
535
 
537
536
  const user_messages = this.messages.filter(m => m.role === 'user').length;
538
537
  if (user_messages >= 30) {
539
- this.addMessage(
540
- 'system',
541
- 'Vous avez atteint la limite de 30 messages. Veuillez contacter un agent ou écrire à support@travelplanet.com.'
542
- );
538
+ this.addMessage('system', 'Vous avez atteint la limite de 30 messages. Veuillez contacter un agent ou écrire à support@travelplanet.com.');
543
539
  const input_bar = this.querySelector('#tp-chatbot-input-bar');
544
540
  if (input_bar) input_bar.style.display = 'none';
545
541
  return;
@@ -623,10 +619,7 @@
623
619
  const server_status = conv.status;
624
620
  const is_typing = conv.is_typing || false;
625
621
 
626
- if (server_status === 'closed' && !this.is_closed) {
627
- this.showClosed();
628
- return;
629
- }
622
+ if (server_status === 'closed' && !this.is_closed) { this.showClosed(); return; }
630
623
 
631
624
  if (is_typing && server_status === 'agent') {
632
625
  if (!this.querySelector('#tp-agent-typing')) {
@@ -680,4 +673,4 @@
680
673
  }
681
674
 
682
675
  customElements.define('tp-chatbot', TpChatbot);
683
- })();
676
+ })();