abdelhak66 commited on
Commit
ddbad68
·
verified ·
1 Parent(s): 6fe7465

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +589 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Customer Support
3
- emoji: 📚
4
- colorFrom: yellow
5
- colorTo: indigo
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: customer-support
3
+ emoji: 🐳
4
+ colorFrom: gray
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,589 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>24/7 Multilingual Customer Support</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .chat-container {
11
+ height: 500px;
12
+ transition: all 0.3s ease;
13
+ }
14
+ .message {
15
+ max-width: 80%;
16
+ word-wrap: break-word;
17
+ }
18
+ .user-message {
19
+ background-color: #3b82f6;
20
+ color: white;
21
+ border-radius: 18px 18px 0 18px;
22
+ }
23
+ .bot-message {
24
+ background-color: #f3f4f6;
25
+ color: #1f2937;
26
+ border-radius: 18px 18px 18px 0;
27
+ }
28
+ .typing-indicator::after {
29
+ content: "...";
30
+ animation: typing 1.5s infinite;
31
+ }
32
+ @keyframes typing {
33
+ 0% { content: "."; }
34
+ 33% { content: ".."; }
35
+ 66% { content: "..."; }
36
+ }
37
+ .language-flag {
38
+ width: 24px;
39
+ height: 16px;
40
+ display: inline-block;
41
+ margin-right: 5px;
42
+ background-size: cover;
43
+ border-radius: 2px;
44
+ }
45
+ .calendly-badge {
46
+ background-color: #006bff;
47
+ color: white;
48
+ padding: 8px 12px;
49
+ border-radius: 4px;
50
+ display: inline-block;
51
+ margin-top: 8px;
52
+ font-weight: bold;
53
+ }
54
+ </style>
55
+ </head>
56
+ <body class="bg-gray-100">
57
+ <div class="container mx-auto max-w-4xl py-8 px-4">
58
+ <div class="bg-white rounded-xl shadow-xl overflow-hidden">
59
+ <!-- Header -->
60
+ <div class="bg-blue-600 text-white p-6 flex items-center justify-between">
61
+ <div class="flex items-center">
62
+ <div class="bg-white rounded-full p-2 mr-4">
63
+ <i class="fas fa-headset text-blue-600 text-2xl"></i>
64
+ </div>
65
+ <div>
66
+ <h1 class="text-2xl font-bold">24/7 Customer Support</h1>
67
+ <p class="text-blue-100">Hi there! How can I help you today?</p>
68
+ </div>
69
+ </div>
70
+ <div class="flex space-x-2">
71
+ <button id="lang-en" class="lang-btn bg-blue-500 hover:bg-blue-700 text-white px-3 py-1 rounded-full text-sm flex items-center" data-lang="en">
72
+ <span class="language-flag" style="background-image: url('https://flagcdn.com/w20/gb.png')"></span> EN
73
+ </button>
74
+ <button id="lang-es" class="lang-btn bg-blue-500 hover:bg-blue-700 text-white px-3 py-1 rounded-full text-sm flex items-center" data-lang="es">
75
+ <span class="language-flag" style="background-image: url('https://flagcdn.com/w20/es.png')"></span> ES
76
+ </button>
77
+ <button id="lang-fr" class="lang-btn bg-blue-500 hover:bg-blue-700 text-white px-3 py-1 rounded-full text-sm flex items-center" data-lang="fr">
78
+ <span class="language-flag" style="background-image: url('https://flagcdn.com/w20/fr.png')"></span> FR
79
+ </button>
80
+ </div>
81
+ </div>
82
+
83
+ <!-- Chat Container -->
84
+ <div class="chat-container p-4 overflow-y-auto bg-gray-50" id="chat-container">
85
+ <div class="flex mb-4 justify-start">
86
+ <div class="message bot-message p-4">
87
+ <p>Hello! I'm your 24/7 multilingual customer support assistant. How can I help you today?</p>
88
+ <div class="mt-2 flex flex-wrap gap-2">
89
+ <button class="quick-reply bg-white text-blue-600 px-3 py-1 rounded-full text-sm border border-blue-200 hover:bg-blue-50">Pricing</button>
90
+ <button class="quick-reply bg-white text-blue-600 px-3 py-1 rounded-full text-sm border border-blue-200 hover:bg-blue-50">Business Hours</button>
91
+ <button class="quick-reply bg-white text-blue-600 px-3 py-1 rounded-full text-sm border border-blue-200 hover:bg-blue-50">Services</button>
92
+ <button class="quick-reply bg-white text-blue-600 px-3 py-1 rounded-full text-sm border border-blue-200 hover:bg-blue-50">Return Policy</button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Input Area -->
99
+ <div class="p-4 border-t border-gray-200 bg-white">
100
+ <div class="flex items-center">
101
+ <input type="text" id="user-input" placeholder="Type your message here..." class="flex-1 border border-gray-300 rounded-full py-2 px-4 focus:outline-none focus:ring-2 focus:ring-blue-500">
102
+ <button id="send-btn" class="ml-2 bg-blue-600 text-white rounded-full p-2 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
103
+ <i class="fas fa-paper-plane"></i>
104
+ </button>
105
+ </div>
106
+ <div class="mt-2 text-xs text-gray-500">
107
+ <p>By using this chat, you agree to our <a href="#" class="text-blue-600 hover:underline">Privacy Policy</a></p>
108
+ </div>
109
+ </div>
110
+ </div>
111
+ </div>
112
+
113
+ <script>
114
+ // Current language (default English)
115
+ let currentLang = 'en';
116
+
117
+ // Translation dictionary
118
+ const translations = {
119
+ en: {
120
+ greeting: "Hello! I'm your 24/7 multilingual customer support assistant. How can I help you today?",
121
+ quickReplies: ["Pricing", "Business Hours", "Services", "Return Policy"],
122
+ inputPlaceholder: "Type your message here...",
123
+ privacyText: "By using this chat, you agree to our Privacy Policy",
124
+ faqResponses: {
125
+ "Pricing": "Our pricing varies depending on the service. For detailed pricing information, please visit our <a href='/pricing' class='text-blue-600 hover:underline'>pricing page</a>. Would you like me to check pricing for a specific service?",
126
+ "Business Hours": "Our customer support is available 24/7. Our physical locations are open Monday to Friday from 9 AM to 6 PM.",
127
+ "Services": "We offer a wide range of services including [list services]. Which service are you interested in?",
128
+ "Return Policy": "Our return policy allows returns within 30 days of purchase with a receipt. For more details, please see our <a href='/returns' class='text-blue-600 hover:underline'>return policy page</a>."
129
+ },
130
+ leadQuestions: [
131
+ "What service do you need?",
132
+ "What's your timeline for this service?",
133
+ "How can we contact you for follow-up? (Email/Phone)"
134
+ ],
135
+ schedulePrompt: "Would you like to schedule an appointment? Here's our real-time availability:",
136
+ confirmation: "I've sent a confirmation to your email/SMS. Is there anything else I can help with?",
137
+ escalation: "I'm connecting you with a human agent now. Please hold..."
138
+ },
139
+ es: {
140
+ greeting: "¡Hola! Soy tu asistente de servicio al cliente multilingüe 24/7. ¿Cómo puedo ayudarte hoy?",
141
+ quickReplies: ["Precios", "Horario", "Servicios", "Política de devolución"],
142
+ inputPlaceholder: "Escribe tu mensaje aquí...",
143
+ privacyText: "Al usar este chat, aceptas nuestra Política de privacidad",
144
+ faqResponses: {
145
+ "Precios": "Nuestros precios varían según el servicio. Para información detallada, visita nuestra <a href='/pricing' class='text-blue-600 hover:underline'>página de precios</a>. ¿Te gustaría que revise el precio de un servicio específico?",
146
+ "Horario": "Nuestro servicio al cliente está disponible 24/7. Nuestras ubicaciones físicas están abiertas de lunes a viernes de 9 AM a 6 PM.",
147
+ "Servicios": "Ofrecemos una amplia gama de servicios que incluyen [lista de servicios]. ¿Qué servicio te interesa?",
148
+ "Política de devolución": "Nuestra política de devolución permite devoluciones dentro de los 30 días posteriores a la compra con recibo. Para más detalles, consulta nuestra <a href='/returns' class='text-blue-600 hover:underline'>página de política de devolución</a>."
149
+ },
150
+ leadQuestions: [
151
+ "¿Qué servicio necesitas?",
152
+ "¿Cuál es tu plazo para este servicio?",
153
+ "¿Cómo podemos contactarte para seguimiento? (Correo electrónico/Teléfono)"
154
+ ],
155
+ schedulePrompt: "¿Te gustaría programar una cita? Aquí está nuestra disponibilidad en tiempo real:",
156
+ confirmation: "He enviado una confirmación a tu correo electrónico/SMS. ¿Hay algo más en lo que pueda ayudar?",
157
+ escalation: "Te estoy conectando con un agente humano ahora. Por favor espera..."
158
+ },
159
+ fr: {
160
+ greeting: "Bonjour ! Je suis votre assistant de service client multilingue 24/7. Comment puis-je vous aider aujourd'hui ?",
161
+ quickReplies: ["Tarifs", "Heures d'ouverture", "Services", "Politique de retour"],
162
+ inputPlaceholder: "Tapez votre message ici...",
163
+ privacyText: "En utilisant ce chat, vous acceptez notre Politique de confidentialité",
164
+ faqResponses: {
165
+ "Tarifs": "Nos tarifs varient selon le service. Pour des informations tarifaires détaillées, veuillez visiter notre <a href='/pricing' class='text-blue-600 hover:underline'>page de tarification</a>. Souhaitez-vous que je vérifie le tarif d'un service spécifique ?",
166
+ "Heures d'ouverture": "Notre service client est disponible 24h/24 et 7j/7. Nos emplacements physiques sont ouverts du lundi au vendredi de 9h à 18h.",
167
+ "Services": "Nous proposons une large gamme de services incluant [liste des services]. Quel service vous intéresse ?",
168
+ "Politique de retour": "Notre politique de retour autorise les retours dans les 30 jours suivant l'achat avec un reçu. Pour plus de détails, veuillez consulter notre <a href='/returns' class='text-blue-600 hover:underline'>page de politique de retour</a>."
169
+ },
170
+ leadQuestions: [
171
+ "De quel service avez-vous besoin ?",
172
+ "Quel est votre délai pour ce service ?",
173
+ "Comment pouvons-nous vous contacter pour un suivi ? (Email/Téléphone)"
174
+ ],
175
+ schedulePrompt: "Souhaitez-vous prendre rendez-vous ? Voici notre disponibilité en temps réel :",
176
+ confirmation: "J'ai envoyé une confirmation à votre email/SMS. Puis-je vous aider avec autre chose ?",
177
+ escalation: "Je vous connecte avec un agent humain maintenant. Veuillez patienter..."
178
+ }
179
+ };
180
+
181
+ // Chat state
182
+ let chatState = {
183
+ isQualifyingLead: false,
184
+ leadQuestionsAsked: 0,
185
+ leadAnswers: [],
186
+ unresolvedQuestions: 0,
187
+ waitingForAppointment: false,
188
+ currentLeadData: null
189
+ };
190
+
191
+ // DOM elements
192
+ const chatContainer = document.getElementById('chat-container');
193
+ const userInput = document.getElementById('user-input');
194
+ const sendBtn = document.getElementById('send-btn');
195
+ const langButtons = document.querySelectorAll('.lang-btn');
196
+ const quickReplyButtons = document.querySelectorAll('.quick-reply');
197
+
198
+ // Initialize chat
199
+ function initChat() {
200
+ // Set language buttons active state
201
+ langButtons.forEach(btn => {
202
+ if (btn.dataset.lang === currentLang) {
203
+ btn.classList.add('bg-blue-700');
204
+ } else {
205
+ btn.classList.remove('bg-blue-700');
206
+ }
207
+ });
208
+
209
+ // Update UI elements with translations
210
+ userInput.placeholder = translations[currentLang].inputPlaceholder;
211
+ }
212
+
213
+ // Add message to chat
214
+ function addMessage(text, isUser = false) {
215
+ const messageDiv = document.createElement('div');
216
+ messageDiv.className = `flex mb-4 ${isUser ? 'justify-end' : 'justify-start'}`;
217
+
218
+ const messageContent = document.createElement('div');
219
+ messageContent.className = `message ${isUser ? 'user-message' : 'bot-message'} p-4`;
220
+ messageContent.innerHTML = text;
221
+
222
+ messageDiv.appendChild(messageContent);
223
+ chatContainer.appendChild(messageDiv);
224
+
225
+ // Scroll to bottom
226
+ chatContainer.scrollTop = chatContainer.scrollHeight;
227
+ }
228
+
229
+ // Show typing indicator
230
+ function showTypingIndicator() {
231
+ const typingDiv = document.createElement('div');
232
+ typingDiv.className = 'flex mb-4 justify-start';
233
+
234
+ const typingContent = document.createElement('div');
235
+ typingContent.className = 'message bot-message p-4';
236
+ typingContent.innerHTML = '<span class="typing-indicator"></span>';
237
+
238
+ typingDiv.appendChild(typingContent);
239
+ chatContainer.appendChild(typingDiv);
240
+ chatContainer.scrollTop = chatContainer.scrollHeight;
241
+
242
+ return typingDiv;
243
+ }
244
+
245
+ // Hide typing indicator
246
+ function hideTypingIndicator(typingDiv) {
247
+ if (typingDiv && typingDiv.parentNode) {
248
+ typingDiv.parentNode.removeChild(typingDiv);
249
+ }
250
+ }
251
+
252
+ // Process user input
253
+ function processInput() {
254
+ const inputText = userInput.value.trim();
255
+ if (!inputText) return;
256
+
257
+ // Add user message to chat
258
+ addMessage(inputText, true);
259
+ userInput.value = '';
260
+
261
+ // Check for escalation triggers
262
+ if (inputText.toLowerCase().includes('agent') ||
263
+ chatState.unresolvedQuestions >= 3 ||
264
+ inputText.toLowerCase().includes('payment issue')) {
265
+ escalateToHuman();
266
+ return;
267
+ }
268
+
269
+ // Process based on current state
270
+ if (chatState.isQualifyingLead) {
271
+ processLeadQualification(inputText);
272
+ } else if (chatState.waitingForAppointment) {
273
+ processAppointmentConfirmation(inputText);
274
+ } else {
275
+ processGeneralInquiry(inputText);
276
+ }
277
+ }
278
+
279
+ // Process general inquiry
280
+ function processGeneralInquiry(inputText) {
281
+ const typingDiv = showTypingIndicator();
282
+
283
+ // Simulate processing delay
284
+ setTimeout(() => {
285
+ hideTypingIndicator(typingDiv);
286
+
287
+ // Check if this is a FAQ
288
+ let isFAQ = false;
289
+ for (const [key, value] of Object.entries(translations[currentLang].faqResponses)) {
290
+ if (inputText.toLowerCase().includes(key.toLowerCase())) {
291
+ addMessage(value);
292
+ isFAQ = true;
293
+
294
+ // If it's a service question, start lead qualification
295
+ if (key === 'Services' || key === 'Servicios' || key === 'Services') {
296
+ setTimeout(() => startLeadQualification(), 1000);
297
+ }
298
+ break;
299
+ }
300
+ }
301
+
302
+ if (!isFAQ) {
303
+ // Check if this might be a service request
304
+ if (inputText.toLowerCase().includes('service') ||
305
+ inputText.toLowerCase().includes('servicio') ||
306
+ inputText.toLowerCase().includes('service')) {
307
+ addMessage(translations[currentLang].faqResponses['Services']);
308
+ setTimeout(() => startLeadQualification(), 1000);
309
+ } else {
310
+ addMessage("I'm not sure I understand. Could you please rephrase your question or choose from these options?");
311
+ chatState.unresolvedQuestions++;
312
+
313
+ // Show quick replies
314
+ const quickRepliesDiv = document.createElement('div');
315
+ quickRepliesDiv.className = 'mt-2 flex flex-wrap gap-2';
316
+
317
+ translations[currentLang].quickReplies.forEach(reply => {
318
+ const btn = document.createElement('button');
319
+ btn.className = 'quick-reply bg-white text-blue-600 px-3 py-1 rounded-full text-sm border border-blue-200 hover:bg-blue-50';
320
+ btn.textContent = reply;
321
+ btn.addEventListener('click', () => {
322
+ addMessage(reply, true);
323
+ processGeneralInquiry(reply);
324
+ });
325
+ quickRepliesDiv.appendChild(btn);
326
+ });
327
+
328
+ const lastMessage = chatContainer.lastChild.querySelector('.message');
329
+ lastMessage.appendChild(quickRepliesDiv);
330
+ }
331
+ }
332
+ }, 1000);
333
+ }
334
+
335
+ // Start lead qualification process
336
+ function startLeadQualification() {
337
+ chatState.isQualifyingLead = true;
338
+ chatState.leadQuestionsAsked = 0;
339
+ chatState.leadAnswers = [];
340
+
341
+ const typingDiv = showTypingIndicator();
342
+
343
+ setTimeout(() => {
344
+ hideTypingIndicator(typingDiv);
345
+ addMessage(translations[currentLang].leadQuestions[0]);
346
+ }, 1000);
347
+ }
348
+
349
+ // Process lead qualification answers
350
+ function processLeadQualification(answer) {
351
+ chatState.leadAnswers.push(answer);
352
+ chatState.leadQuestionsAsked++;
353
+
354
+ if (chatState.leadQuestionsAsked < translations[currentLang].leadQuestions.length) {
355
+ // Ask next question
356
+ const typingDiv = showTypingIndicator();
357
+
358
+ setTimeout(() => {
359
+ hideTypingIndicator(typingDiv);
360
+ addMessage(translations[currentLang].leadQuestions[chatState.leadQuestionsAsked]);
361
+ }, 1000);
362
+ } else {
363
+ // All questions answered - qualify lead
364
+ qualifyLead();
365
+ }
366
+ }
367
+
368
+ // Qualify lead based on answers
369
+ function qualifyLead() {
370
+ const typingDiv = showTypingIndicator();
371
+
372
+ setTimeout(() => {
373
+ hideTypingIndicator(typingDiv);
374
+
375
+ // Simple qualification logic
376
+ let leadScore = 0;
377
+ if (chatState.leadAnswers[1].toLowerCase().includes('soon') ||
378
+ chatState.leadAnswers[1].toLowerCase().includes('urgent') ||
379
+ chatState.leadAnswers[1].toLowerCase().includes('pronto') ||
380
+ chatState.leadAnswers[1].toLowerCase().includes('urgente') ||
381
+ chatState.leadAnswers[1].toLowerCase().includes('rapide') ||
382
+ chatState.leadAnswers[1].toLowerCase().includes('urgence')) {
383
+ leadScore = 10;
384
+ } else if (chatState.leadAnswers[1].toLowerCase().includes('next month') ||
385
+ chatState.leadAnswers[1].toLowerCase().includes('proximo mes') ||
386
+ chatState.leadAnswers[1].toLowerCase().includes('le mois prochain')) {
387
+ leadScore = 5;
388
+ }
389
+
390
+ // Create JSON for Lovable.dev
391
+ const leadData = {
392
+ service: chatState.leadAnswers[0],
393
+ timeline: chatState.leadAnswers[1],
394
+ contact: chatState.leadAnswers[2],
395
+ score: leadScore,
396
+ timestamp: new Date().toISOString(),
397
+ language: currentLang
398
+ };
399
+
400
+ // Store lead data for potential scheduling
401
+ chatState.currentLeadData = leadData;
402
+
403
+ // Simulate sending to Lovable.dev webhook
404
+ simulateLovableWebhook(leadData);
405
+
406
+ // Inform user
407
+ let responseText = `Thank you for the information! `;
408
+
409
+ if (leadScore >= 8) {
410
+ responseText += "This sounds urgent! ";
411
+ } else if (leadScore >= 3) {
412
+ responseText += "We'll follow up with you soon. ";
413
+ }
414
+
415
+ responseText += translations[currentLang].schedulePrompt;
416
+
417
+ addMessage(responseText);
418
+
419
+ // Show calendar integration (simulated)
420
+ const calendarDiv = document.createElement('div');
421
+ calendarDiv.className = 'mt-4 p-4 bg-white border border-gray-200 rounded-lg';
422
+ calendarDiv.innerHTML = `
423
+ <h3 class="font-bold mb-2">Available Time Slots</h3>
424
+ <div class="grid grid-cols-2 gap-2">
425
+ <button class="time-slot bg-blue-100 hover:bg-blue-200 text-blue-800 py-2 px-3 rounded">Tomorrow 10 AM</button>
426
+ <button class="time-slot bg-blue-100 hover:bg-blue-200 text-blue-800 py-2 px-3 rounded">Tomorrow 2 PM</button>
427
+ <button class="time-slot bg-blue-100 hover:bg-blue-200 text-blue-800 py-2 px-3 rounded">Friday 11 AM</button>
428
+ <button class="time-slot bg-blue-100 hover:bg-blue-200 text-blue-800 py-2 px-3 rounded">Friday 3 PM</button>
429
+ </div>
430
+ <div class="calendly-badge mt-3">
431
+ <i class="fas fa-calendar-alt mr-2"></i>Powered by Calendly
432
+ </div>
433
+ `;
434
+
435
+ const lastMessage = chatContainer.lastChild.querySelector('.message');
436
+ lastMessage.appendChild(calendarDiv);
437
+
438
+ // Add click handlers to time slots
439
+ document.querySelectorAll('.time-slot').forEach(slot => {
440
+ slot.addEventListener('click', () => {
441
+ const selectedTime = slot.textContent;
442
+ addMessage(selectedTime, true);
443
+ confirmAppointment(selectedTime);
444
+ });
445
+ });
446
+
447
+ chatState.isQualifyingLead = false;
448
+ chatState.waitingForAppointment = true;
449
+ }, 1000);
450
+ }
451
+
452
+ // Simulate Lovable.dev webhook call
453
+ function simulateLovableWebhook(leadData) {
454
+ console.log('Sending to Lovable.dev webhook:', leadData);
455
+
456
+ // In a real implementation, you would use:
457
+ // fetch('https://your-lovable-dev-webhook-url', {
458
+ // method: 'POST',
459
+ // headers: {
460
+ // 'Content-Type': 'application/json',
461
+ // },
462
+ // body: JSON.stringify(leadData)
463
+ // })
464
+
465
+ // For demo purposes, we'll just log it
466
+ const response = {
467
+ status: 'success',
468
+ message: 'Lead processed',
469
+ data: leadData
470
+ };
471
+
472
+ console.log('Lovable.dev response:', response);
473
+ }
474
+
475
+ // Confirm appointment
476
+ function confirmAppointment(time) {
477
+ const typingDiv = showTypingIndicator();
478
+
479
+ setTimeout(() => {
480
+ hideTypingIndicator(typingDiv);
481
+
482
+ // Add appointment time to lead data
483
+ chatState.currentLeadData.appointmentTime = time;
484
+
485
+ // Simulate sending SMS confirmation
486
+ if (chatState.currentLeadData.contact) {
487
+ simulateSMSConfirmation(chatState.currentLeadData.contact, time);
488
+ }
489
+
490
+ addMessage(`Great! I've scheduled your appointment for ${time}. ${translations[currentLang].confirmation}`);
491
+
492
+ chatState.waitingForAppointment = false;
493
+ }, 1000);
494
+ }
495
+
496
+ // Simulate SMS confirmation
497
+ function simulateSMSConfirmation(contact, time) {
498
+ console.log('Sending SMS to:', contact);
499
+ console.log('Message:', `Your appointment is scheduled for ${time}. Reply STOP to unsubscribe.`);
500
+
501
+ // In a real implementation, you would use Twilio:
502
+ // fetch('https://api.twilio.com/2010-04-01/Accounts/YOUR_TWILIO_SID/Messages.json', {
503
+ // method: 'POST',
504
+ // headers: {
505
+ // 'Authorization': 'Basic ' + btoa('YOUR_TWILIO_SID:YOUR_TWILIO_TOKEN'),
506
+ // 'Content-Type': 'application/x-www-form-urlencoded',
507
+ // },
508
+ // body: new URLSearchParams({
509
+ // 'To': contact,
510
+ // 'From': '+1234567890',
511
+ // 'Body': `Your appointment is scheduled for ${time}. Reply STOP to unsubscribe.`
512
+ // })
513
+ // })
514
+ }
515
+
516
+ // Process appointment confirmation response
517
+ function processAppointmentConfirmation(inputText) {
518
+ const typingDiv = showTypingIndicator();
519
+
520
+ setTimeout(() => {
521
+ hideTypingIndicator(typingDiv);
522
+
523
+ if (inputText.toLowerCase().includes('yes') ||
524
+ inputText.toLowerCase().includes('sí') ||
525
+ inputText.toLowerCase().includes('oui')) {
526
+ addMessage("What else can I help you with?");
527
+ } else {
528
+ addMessage("Thank you for chatting with us! Have a great day!");
529
+ }
530
+
531
+ chatState.waitingForAppointment = false;
532
+ }, 1000);
533
+ }
534
+
535
+ // Escalate to human agent
536
+ function escalateToHuman() {
537
+ const typingDiv = showTypingIndicator();
538
+
539
+ setTimeout(() => {
540
+ hideTypingIndicator(typingDiv);
541
+ addMessage(translations[currentLang].escalation);
542
+
543
+ // Simulate transfer
544
+ console.log('Transferring to human agent...');
545
+ }, 1500);
546
+ }
547
+
548
+ // Change language
549
+ function changeLanguage(lang) {
550
+ currentLang = lang;
551
+ initChat();
552
+
553
+ // Add language change message
554
+ const typingDiv = showTypingIndicator();
555
+
556
+ setTimeout(() => {
557
+ hideTypingIndicator(typingDiv);
558
+
559
+ let langName = '';
560
+ if (lang === 'en') langName = 'English';
561
+ if (lang === 'es') langName = 'Spanish';
562
+ if (lang === 'fr') langName = 'French';
563
+
564
+ addMessage(`Language changed to ${langName}. How can I help you?`);
565
+ }, 1000);
566
+ }
567
+
568
+ // Event listeners
569
+ sendBtn.addEventListener('click', processInput);
570
+ userInput.addEventListener('keypress', (e) => {
571
+ if (e.key === 'Enter') processInput();
572
+ });
573
+
574
+ langButtons.forEach(btn => {
575
+ btn.addEventListener('click', () => changeLanguage(btn.dataset.lang));
576
+ });
577
+
578
+ quickReplyButtons.forEach(btn => {
579
+ btn.addEventListener('click', () => {
580
+ addMessage(btn.textContent, true);
581
+ processGeneralInquiry(btn.textContent);
582
+ });
583
+ });
584
+
585
+ // Initialize chat
586
+ initChat();
587
+ </script>
588
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=abdelhak66/customer-support" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
589
+ </html>