Please insure this bit has proper intelligence to not only respond to my live sms or iMessage texts from iOS or android but be able to answer my calls and talk for me . Teach it Spanish as well. I want to also give me a setting so I can have it speak a personal message to the caller once it answers - Follow Up Deployment
9b74755
verified
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>AI Phone Assistant</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<script> | |
// Business settings data | |
let businessSettings = { | |
maxRingTime: 30, | |
smsResponseTime: 15, | |
responseLanguage: "en", | |
personalGreeting: "", | |
businessHours: { | |
open: "08:00", | |
close: "18:00" | |
}, | |
responses: { | |
missedCall: { | |
en: "Hello, this is Jay's Mobile Wash. We missed your call. Please leave a message and we'll return your call as soon as possible.", | |
es: "Hola, es el lavado móvil de Jay. Perdimos su llamada. Por favor deje un mensaje y le devolveremos la llamada lo antes posible." | |
}, | |
afterHours: { | |
en: "Thank you for contacting Jay's Mobile Wash. Our business hours are [hours]. We will respond when we reopen.", | |
es: "Gracias por contactar el lavado móvil de Jay. Nuestro horario es de [hours]. Responderemos cuando volvamos a abrir." | |
} | |
} | |
}; | |
function loadSettings() { | |
const saved = localStorage.getItem('JMW_Settings'); | |
if (saved) { | |
businessSettings = JSON.parse(saved); | |
document.getElementById('maxRingTime').value = businessSettings.maxRingTime; | |
document.getElementById('smsResponseTime').value = businessSettings.smsResponseTime; | |
document.getElementById('openTime').value = businessSettings.businessHours.open; | |
document.getElementById('closeTime').value = businessSettings.businessHours.close; | |
document.getElementById('responseLanguage').value = businessSettings.responseLanguage; | |
document.getElementById('personalGreeting').value = businessSettings.personalGreeting; | |
document.getElementById('missedCallResponse').value = businessSettings.responses.missedCall.en; | |
document.getElementById('missedCallResponseEs').value = businessSettings.responses.missedCall.es; | |
document.getElementById('afterHoursResponse').value = businessSettings.responses.afterHours.en; | |
document.getElementById('afterHoursResponseEs').value = businessSettings.responses.afterHours.es; | |
} | |
} | |
function saveSettings() { | |
businessSettings = { | |
maxRingTime: parseInt(document.getElementById('maxRingTime').value), | |
smsResponseTime: parseInt(document.getElementById('smsResponseTime').value), | |
responseLanguage: document.getElementById('responseLanguage').value, | |
personalGreeting: document.getElementById('personalGreeting').value, | |
businessHours: { | |
open: document.getElementById('openTime').value, | |
close: document.getElementById('closeTime').value | |
}, | |
responses: { | |
missedCall: { | |
en: document.getElementById('missedCallResponse').value, | |
es: document.getElementById('missedCallResponseEs').value | |
}, | |
afterHours: { | |
en: document.getElementById('afterHoursResponse').value, | |
es: document.getElementById('afterHoursResponseEs').value | |
} | |
} | |
}; | |
localStorage.setItem('JMW_Settings', JSON.stringify(businessSettings)); | |
// Show success message | |
const notification = document.createElement('div'); | |
notification.className = 'fixed top-40 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-3 rounded-xl animate-fadeIn z-50 shadow-lg'; | |
notification.innerHTML = 'Settings saved successfully!'; | |
document.body.appendChild(notification); | |
setTimeout(() => notification.remove(), 3000); | |
} | |
// Enhanced answerCall with time-based response | |
function answerCall() { | |
const currentTime = new Date(); | |
const openTime = new Date(); | |
const closeTime = new Date(); | |
const [openHours, openMins] = businessSettings.businessHours.open.split(':'); | |
const [closeHours, closeMins] = businessSettings.businessHours.close.split(':'); | |
openTime.setHours(openHours, openMins); | |
closeTime.setHours(closeHours, closeMins); | |
if (currentTime < openTime || currentTime > closeTime) { | |
const fab = document.querySelector('.fab'); | |
const icon = fab.querySelector('i'); | |
icon.classList.remove('fa-phone'); | |
icon.classList.add('fa-clock'); | |
showResponseMessage(businessSettings.responses.afterHours.replace('[hours]', | |
`${businessSettings.businessHours.open} - ${businessSettings.businessHours.close}`)); | |
setTimeout(() => { | |
icon.classList.remove('fa-clock'); | |
icon.classList.add('fa-phone'); | |
}, 1000); | |
return; | |
} | |
// Original answerCall functionality... | |
} | |
function showResponseMessage(message) { | |
const responseContainer = document.querySelector('#callResponseContainer'); | |
if (!responseContainer) { | |
const container = document.createElement('div'); | |
container.id = 'callResponseContainer'; | |
container.className = 'fixed top-16 left-1/2 transform -translate-x-1/2 bg-black bg-opacity-80 text-white px-4 py-2 rounded-lg z-50'; | |
container.textContent = message; | |
document.body.appendChild(container); | |
setTimeout(() => container.remove(), 3000); | |
} | |
} | |
function exportConfiguration() { | |
const data = { | |
trainingData: trainingData, | |
timestamp: new Date().toISOString(), | |
version: "1.0", | |
aiProfile: "Grok-Style Learning Assistant" | |
}; | |
const blob = new Blob([JSON.stringify(data, null, 2)], {type: 'application/json'}); | |
const url = URL.createObjectURL(blob); | |
const a = document.createElement('a'); | |
a.href = url; | |
a.download = `AI-Call-Assistant-${new Date().toISOString().split('T')[0]}.json`; | |
document.body.appendChild(a); | |
a.click(); | |
document.body.removeChild(a); | |
URL.revokeObjectURL(url); | |
alert("Configuration exported successfully!"); | |
} | |
// Tailwind config | |
tailwind.config = { | |
theme: { | |
extend: { | |
colors: { | |
iosbg: '#f2f2f7', | |
iosdark: '#1c1c1e', | |
accent: '#0a84ff', | |
accent2: '#5e5ce6', | |
} | |
} | |
} | |
} | |
// SMS/iMessage Handling | |
function handleSMS(message, sender, isiMessage) { | |
const responseLanguage = businessSettings.responseLanguage; | |
const greeting = businessSettings.personalGreeting; | |
let response; | |
// Check for Spanish keywords | |
const spanishKeywords = ['hola', 'gracias', 'servicio', 'lavado']; | |
const isSpanish = spanishKeywords.some(word => | |
message.toLowerCase().includes(word)); | |
// Determine best language to respond in | |
const useSpanish = responseLanguage === 'es' || isSpanish; | |
if (message.toLowerCase().includes('appointment') || | |
message.toLowerCase().includes('cita')) { | |
response = useSpanish ? | |
`Gracias por su mensaje. Nuestros horarios para citas son ${businessSettings.businessHours.open} a ${businessSettings.businessHours.close}.` : | |
`Thanks for your message. Our appointment hours are ${businessSettings.businessHours.open} to ${businessSettings.businessHours.close}.`; | |
} else if (greeting && !isiMessage) { | |
// Use personal greeting for SMS (not iMessage) | |
response = greeting; | |
} else { | |
response = useSpanish ? | |
"Gracias por su mensaje. ¿En qué puedo ayudarle hoy?" : | |
"Thanks for your message. How can I help you today?"; | |
} | |
return response; | |
} | |
// Call Answering with Speech Synthesis | |
function answerCallWithSpeech(callerNumber) { | |
const synth = window.speechSynthesis; | |
const utterance = new SpeechSynthesisUtterance(); | |
const greeting = businessSettings.personalGreeting || | |
(businessSettings.responseLanguage === 'es' ? | |
"Buenos días, habla el asistente de Jay's Mobile Wash. ¿En qué puedo ayudarle?" : | |
"Hello, this is Jay's Mobile Wash assistant. How can I help you?"); | |
utterance.text = greeting; | |
utterance.lang = businessSettings.responseLanguage === 'es' ? 'es-ES' : 'en-US'; | |
// Speak the greeting | |
synth.speak(utterance); | |
// Set up voice recognition for caller response | |
if ('webkitSpeechRecognition' in window) { | |
const recognition = new webkitSpeechRecognition(); | |
recognition.lang = businessSettings.responseLanguage === 'es' ? 'es-ES' : 'en-US'; | |
recognition.interimResults = false; | |
recognition.onresult = function(event) { | |
const transcript = event.results[0][0].transcript; | |
// Process caller's speech and respond | |
processCallerSpeech(transcript, recognition); | |
}; | |
recognition.start(); | |
} | |
} | |
function processCallerSpeech(transcript, recognition) { | |
const synth = window.speechSynthesis; | |
const utterance = new SpeechSynthesisUtterance(); | |
utterance.lang = businessSettings.responseLanguage === 'es' ? 'es-ES' : 'en-US'; | |
// Simple response logic - would be enhanced with AI in production | |
if (transcript.toLowerCase().includes('appointment') || | |
transcript.toLowerCase().includes('cita')) { | |
utterance.text = businessSettings.responseLanguage === 'es' ? | |
`Las citas están disponibles de ${businessSettings.businessHours.open} a ${businessSettings.businessHours.close}.` : | |
`Appointments are available from ${businessSettings.businessHours.open} to ${businessSettings.businessHours.close}.`; | |
} else { | |
utterance.text = businessSettings.responseLanguage === 'es' ? | |
"Por favor visite nuestro sitio web jaysmobilewash.com para más información. ¿Algo más en lo que pueda ayudarle?" : | |
"Please visit our website jaysmobilewash.com for more information. Is there anything else I can help with?"; | |
} | |
synth.speak(utterance); | |
// Continue listening for next input | |
setTimeout(() => recognition.start(), 2000); | |
} | |
</script> | |
<style> | |
body { | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; | |
} | |
.screen { | |
display: none; | |
} | |
.screen.active { | |
display: block; | |
} | |
/* Simple switch */ | |
.toggle-switch { | |
position: relative; | |
display: inline-block; | |
width: 60px; | |
height: 34px; | |
} | |
.toggle-switch input { | |
opacity: 0; | |
width: 0; | |
height: 0; | |
} | |
.slider { | |
position: absolute; | |
cursor: pointer; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: #ccc; | |
transition: .4s; | |
border-radius: 34px; | |
} | |
.slider:before { | |
position: absolute; | |
content: ""; | |
height: 26px; | |
width: 26px; | |
left: 4px; | |
bottom: 4px; | |
background-color: white; | |
transition: .4s; | |
border-radius: 50%; | |
} | |
input:checked + .slider { | |
background-color: #2196F3; | |
} | |
input:checked + .slider:before { | |
transform: translateX(26px); | |
} | |
/* Chat bubbles */ | |
.ai-bubble { | |
background: #f1f1f1; | |
border-radius: 5px 15px 15px 5px; | |
padding: 10px 15px; | |
max-width: 85%; | |
margin: 5px 0; | |
} | |
.user-bubble { | |
background: #2196F3; | |
color: white; | |
border-radius: 15px 5px 5px 15px; | |
padding: 10px 15px; | |
max-width: 85%; | |
margin: 5px 0 5px auto; | |
} | |
/* Simple buttons */ | |
.simple-btn { | |
background: #2196F3; | |
color: white; | |
border: none; | |
padding: 10px 15px; | |
border-radius: 5px; | |
cursor: pointer; | |
margin: 5px; | |
} | |
/* Function buttons */ | |
.action-btn { | |
background: #4CAF50; | |
color: white; | |
border: none; | |
padding: 10px 15px; | |
border-radius: 5px; | |
cursor: pointer; | |
margin: 5px; | |
} | |
</style> | |
</head> | |
<body class="bg-iosbg dark:bg-iosdark text-gray-900 dark:text-gray-200 min-h-screen"> | |
<!-- Status Bar --> | |
<div class="fixed top-0 left-0 right-0 h-12 flex items-center px-4 z-50 bg-iosbg dark:bg-iosdark"> | |
<div class="text-left text-sm w-20">9:41</div> | |
<div class="flex-1 flex justify-center"> | |
<i class="fas fa-signal mr-2"></i> | |
<i class="fas fa-wifi mr-2"></i> | |
<i class="fas fa-battery-three-quarters"></i> | |
</div> | |
<div class="w-20 text-right text-xs">100%</div> | |
</div> | |
<!-- Main App Container --> | |
<div class="relative pt-12 max-w-md mx-auto h-screen overflow-hidden"> | |
<!-- Home Screen --> | |
<div id="homeScreen" class="screen active px-4 pt-4 h-full flex flex-col"> | |
<div class="mt-2"> | |
<h1 class="text-3xl font-bold">Jay's Mobile Wash</h1> | |
<p class="text-gray-500 dark:text-gray-400 mt-1">AI Call Assistant Dashboard</p> | |
</div> | |
<!-- Quick Action Buttons --> | |
<div class="mt-8 grid grid-cols-2 gap-4"> | |
<button onclick="showScreen('repliesScreen')" class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex flex-col items-center shadow-sm"> | |
<div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center mb-3"> | |
<i class="fas fa-comments text-blue-500 text-xl"></i> | |
</div> | |
<h3 class="font-medium">Response Templates</h3> | |
<p class="text-xs text-gray-500 mt-1 text-center">Pre-set replies for common calls</p> | |
</button> | |
<button onclick="showScreen('trainingScreen')" class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex flex-col items-center shadow-sm"> | |
<div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center mb-3"> | |
<i class="fas fa-graduation-cap text-purple-500 text-xl"></i> | |
</div> | |
<h3 class="font-medium">Train AI</h3> | |
<p class="text-xs text-gray-500 mt-1 text-center">Improve call responses</p> | |
</button> | |
<button onclick="showScreen('settingsScreen')" class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex flex-col items-center shadow-sm"> | |
<div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center mb-3"> | |
<i class="fas fa-cog text-green-500 text-xl"></i> | |
</div> | |
<h3 class="font-medium">Settings</h3> | |
<p class="text-xs text-gray-500 mt-1 text-center">Configure call handling</p> | |
</button> | |
<button onclick="answerCall(true)" class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex flex-col items-center shadow-sm"> | |
<div class="w-12 h-12 rounded-full bg-red-100 flex items-center justify-center mb-3"> | |
<i class="fas fa-phone text-red-500 text-xl"></i> | |
</div> | |
<h3 class="font-medium">Test Call</h3> | |
<p class="text-xs text-gray-500 mt-1 text-center">Practice AI responses</p> | |
</button> | |
</div> | |
<!-- Today's Summary --> | |
<div class="mt-8 bg-white dark:bg-gray-800 rounded-2xl p-5"> | |
<h2 class="font-bold text-lg mb-3">Today's Summary</h2> | |
<div class="grid grid-cols-3 gap-4 text-center"> | |
<div class="bg-blue-50 dark:bg-blue-900/30 p-3 rounded-xl"> | |
<div class="text-2xl font-bold">12</div> | |
<div class="text-xs">Calls</div> | |
</div> | |
<div class="bg-green-50 dark:bg-green-900/30 p-3 rounded-xl"> | |
<div class="text-2xl font-bold">8</div> | |
<div class="text-xs">Answered</div> | |
</div> | |
<div class="bg-yellow-50 dark:bg-yellow-900/30 p-3 rounded-xl"> | |
<div class="text-2xl font-bold">4</div> | |
<div class="text-xs">Missed</div> | |
</div> | |
</div> | |
</div> | |
<!-- Recent Activity --> | |
<div class="mt-4"> | |
<div class="flex justify-between items-center mb-2"> | |
<h3 class="font-medium">Recent Calls</h3> | |
<button class="text-sm text-blue-500">See All</button> | |
</div> | |
<div class="space-y-2"> | |
<div class="flex items-center justify-between p-3 bg-white dark:bg-gray-800 rounded-xl"> | |
<div class="flex items-center"> | |
<div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-3"> | |
<i class="fas fa-check text-green-500 text-xs"></i> | |
</div> | |
<div> | |
<p class="text-sm font-medium">(562) 228-9429</p> | |
<p class="text-xs text-gray-500">AI Answered - 2:15 PM</p> | |
</div> | |
</div> | |
<i class="fas fa-chevron-right text-gray-400"></i> | |
</div> | |
<div class="flex items-center justify-between p-3 bg-white dark:bg-gray-800 rounded-xl"> | |
<div class="flex items-center"> | |
<div class="w-8 h-8 rounded-full bg-red-100 flex items-center justify-center mr-3"> | |
<i class="fas fa-times text-red-500 text-xs"></i> | |
</div> | |
<div> | |
<p class="text-sm font-medium">Unknown Caller</p> | |
<p class="text-xs text-gray-500">Missed - 10:45 AM</p> | |
</div> | |
</div> | |
<i class="fas fa-chevron-right text-gray-400"></i> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Configure Replies Screen --> | |
<div id="repliesScreen" class="screen h-full flex flex-col"> | |
<div class="px-4 pt-4"> | |
<div class="flex items-center"> | |
<button class="p-2 rounded-full" onclick="showScreen('homeScreen')"> | |
<i class="fas fa-arrow-left"></i> | |
</button> | |
<h2 class="text-xl font-bold ml-2">Smart Replies</h2> | |
</div> | |
<p class="text-gray-500 dark:text-gray-400 mt-1 ml-12">Customize how AI answers calls</p> | |
</div> | |
<div class="mt-4 px-4 flex-1 overflow-y-auto"> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl p-5 mb-4"> | |
<div class="flex items-center"> | |
<div class="w-12 h-12 rounded-full bg-gradient-to-br from-accent to-accent2 flex items-center justify-center"> | |
<i class="fas fa-brain text-white text-xl"></i> | |
</div> | |
<div class="ml-3"> | |
<h3 class="font-medium">AI Learning Mode</h3> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Improves responses over time</p> | |
</div> | |
</div> | |
<div class="mt-4 flex items-center justify-between"> | |
<span>Learning from interactions</span> | |
<label class="ios-switch"> | |
<input type="checkbox" checked> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
</div> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl overflow-hidden"> | |
<div class="px-5 pt-4"> | |
<h3 class="font-medium">Custom Response Templates</h3> | |
<p class="text-gray-500 dark:text-gray-400 text-sm mt-1">Set predefined responses</p> | |
</div> | |
<div class="mt-4 space-y-2"> | |
<div class="flex items-center justify-between p-4 hover:bg-gray-100 dark:hover:bg-gray-750 cursor-pointer"> | |
<div> | |
<h4 class="font-medium">Business Calls</h4> | |
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">"Hello, this is [Your Name]'s assistant..."</p> | |
</div> | |
<i class="fas fa-chevron-right text-gray-400"></i> | |
</div> | |
<div class="flex items-center justify-between p-4 hover:bg-gray-100 dark:hover:bg-gray-750 cursor-pointer"> | |
<div> | |
<h4 class="font-medium">Personal Calls</h4> | |
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">"Hi, this is [Name]'s phone..."</p> | |
</div> | |
<i class="fas fa-chevron-right text-gray-400"></i> | |
</div> | |
<div class="flex items-center justify-between p-4 hover:bg-gray-100 dark:hover:bg-gray-750 cursor-pointer"> | |
<div> | |
<h4 class="font-medium">Spam Protection</h4> | |
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">"Sorry, this number is not accepting calls..."</p> | |
</div> | |
<i class="fas fa-chevron-right text-gray-400"></i> | |
</div> | |
</div> | |
</div> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl mt-4 p-5"> | |
<h3 class="font-medium">Response Style</h3> | |
<div class="mt-4 space-y-4"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4 class="font-medium">Formal Tone</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Professional business language</p> | |
</div> | |
<label class="ios-switch"> | |
<input type="checkbox" checked> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4 class="font-medium">Friendly Tone</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Casual conversation style</p> | |
</div> | |
<label class="ios-switch"> | |
<input type="checkbox"> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4 class="font-medium">Use My Name</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">"This is [Your Name]'s phone"</p> | |
</div> | |
<label class="ios-switch"> | |
<input type="checkbox" checked> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Call Training Screen --> | |
<div id="trainingScreen" class="screen h-full flex flex-col"> | |
<div class="px-4 pt-4"> | |
<div class="flex items-center justify-between"> | |
<div class="flex items-center"> | |
<button class="p-2 rounded-full" onclick="showScreen('homeScreen')"> | |
<i class="fas fa-arrow-left"></i> | |
</button> | |
<div class="ml-2"> | |
<h2 class="text-xl font-bold">Train AI</h2> | |
<p class="text-gray-500 dark:text-gray-400 text-sm -mt-1">Linked to (562) 228-9429</p> | |
</div> | |
</div> | |
<button class="text-accent" id="saveTraining">Save</button> | |
</div> | |
</div> | |
<div class="mt-4 px-4 flex-1 overflow-hidden flex flex-col"> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex-1 overflow-hidden flex flex-col"> | |
<div class="flex-1 overflow-y-auto pb-4"> | |
<div class="ai-bubble"> | |
<p>How would you like me to respond to calls from your family?</p> | |
</div> | |
<div class="user-bubble mt-4"> | |
<p>Always transfer calls from Mom and Dad to me</p> | |
</div> | |
<div class="ai-bubble mt-4"> | |
<p>Noted! I'll transfer calls from Mom and Dad immediately.</p> | |
<p class="mt-2">For other family members, how should I respond?</p> | |
</div> | |
<div class="user-bubble mt-4"> | |
<p>Ask them for the reason of calling and text me if it's important</p> | |
</div> | |
<div class="ai-bubble mt-4"> | |
<p>Got it. Here's the response I created based on your feedback:</p> | |
<div class="mt-2 bg-blue-50 dark:bg-blue-900 rounded-lg p-3"> | |
<p>"Hello, this is Alex's assistant. Could you let me know what you're calling about? I'll make sure they get your message."</p> | |
</div> | |
<p class="mt-2">Does this work?</p> | |
</div> | |
</div> | |
<div class="mt-auto pt-4 border-t border-gray-200 dark:border-gray-700"> | |
<div class="flex gap-2"> | |
<input id="trainingInput" type="text" class="ios-input flex-1" placeholder="Teach your assistant..." onkeypress="handleTrainingKeyPress(event)"> | |
<button class="w-12 h-12 rounded-xl bg-accent flex items-center justify-center text-white" onclick="submitTraining()"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
<p class="text-xs text-gray-500 dark:text-gray-400 mt-2 text-center">The AI learns from every interaction</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Simplified Navigation --> | |
<div class="fixed bottom-0 left-0 right-0 bg-white shadow-lg p-2 flex justify-around"> | |
<button class="flex flex-col items-center text-xs" onclick="showScreen('homeScreen')"> | |
<i class="fas fa-home mb-1"></i> | |
<span>Home</span> | |
</button> | |
<button class="flex flex-col items-center text-xs" onclick="showScreen('repliesScreen')"> | |
<i class="fas fa-comments mb-1"></i> | |
<span>Replies</span> | |
</button> | |
<button class="flex flex-col items-center text-xs" onclick="showScreen('trainingScreen')"> | |
<i class="fas fa-graduation-cap mb-1"></i> | |
<span>Train</span> | |
</button> | |
<button class="flex flex-col items-center text-xs" onclick="showScreen('settingsScreen')"> | |
<i class="fas fa-cog mb-1"></i> | |
<span>Settings</span> | |
</button> | |
</div> | |
<!-- AI Chat Test Screen --> | |
<div id="chatScreen" class="screen h-full flex flex-col"> | |
<div class="px-4 pt-4"> | |
<div class="flex items-center"> | |
<button class="p-2 rounded-full" onclick="showScreen('homeScreen')"> | |
<i class="fas fa-arrow-left"></i> | |
</button> | |
<h2 class="text-xl font-bold ml-2">AI Chat Test</h2> | |
</div> | |
<p class="text-gray-500 dark:text-gray-400 mt-1 ml-12">Test and train the AI assistant</p> | |
</div> | |
<div class="mt-4 px-4 flex-1 overflow-hidden flex flex-col"> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl p-5 flex-1 overflow-hidden flex flex-col"> | |
<div id="chatMessages" class="flex-1 overflow-y-auto pb-4 space-y-4"> | |
<div class="ai-bubble animate-fadeIn"> | |
<p>Hi! I'm your AI assistant for Jay's Mobile Wash. I can answer questions about our detailing services and learn from our conversations.</p> | |
<p class="mt-2">Would you like to test my knowledge or teach me something new?</p> | |
</div> | |
</div> | |
<div class="mt-auto pt-4 border-t border-gray-200 dark:border-gray-700"> | |
<div class="flex gap-2"> | |
<input id="chatInput" type="text" class="ios-input flex-1" placeholder="Ask or teach me..." onkeypress="handleChatKeyPress(event)"> | |
<button class="w-12 h-12 rounded-xl bg-accent flex items-center justify-center text-white" onclick="submitChatMessage()"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
<p class="text-xs text-gray-500 dark:text-gray-400 mt-2 text-center">I'll learn from every interaction</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Settings Screen --> | |
<div id="settingsScreen" class="screen h-full flex flex-col"> | |
<div class="px-4 pt-4"> | |
<div class="flex items-center"> | |
<button class="p-2 rounded-full" onclick="showScreen('homeScreen')"> | |
<i class="fas fa-arrow-left"></i> | |
</button> | |
<h2 class="text-xl font-bold ml-2">Jay's Mobile Wash Settings</h2> | |
</div> | |
<p class="text-gray-500 dark:text-gray-400 mt-1 ml-12">Configure AI response behavior</p> | |
</div> | |
<div class="mt-4 px-4 flex-1 overflow-y-auto"> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl p-5 mb-4"> | |
<h3 class="font-medium mb-4">Call Response Timing</h3> | |
<div class="space-y-4"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4>Max Ring Time (seconds)</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">If you don't answer by this time, AI will answer</p> | |
</div> | |
<input type="number" id="maxRingTime" value="30" min="5" max="60" class="w-20 px-2 py-1 rounded-lg border border-gray-300"> | |
</div> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4>No-Response Text After (minutes)</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">If you don't reply to SMS by this time</p> | |
</div> | |
<input type="number" id="smsResponseTime" value="15" min="1" max="120" class="w-20 px-2 py-1 rounded-lg border border-gray-300"> | |
</div> | |
<div class="border-t border-gray-200 dark:border-gray-700 pt-4"> | |
<h3 class="font-medium mb-2">Business Hours</h3> | |
<div class="grid grid-cols-2 gap-3"> | |
<div> | |
<label class="block text-sm text-gray-500 dark:text-gray-400 mb-1">Open Time</label> | |
<input type="time" id="openTime" value="08:00" class="w-full px-2 py-1 rounded-lg border border-gray-300"> | |
</div> | |
<div> | |
<label class="block text-sm text-gray-500 dark:text-gray-400 mb-1">Close Time</label> | |
<input type="time" id="closeTime" value="18:00" class="w-full px-2 py-1 rounded-lg border border-gray-300"> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="bg-white dark:bg-gray-800 rounded-2xl p-5"> | |
<h3 class="font-medium mb-4">Call Handling Configuration</h3> | |
<div class="flex items-center justify-between mb-4"> | |
<div> | |
<h4>Answer Incoming Calls</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Enable AI to answer phone calls</p> | |
</div> | |
<label class="ios-switch"> | |
<input type="checkbox" id="answerCallsToggle" checked> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
<div class="flex items-center justify-between mb-4"> | |
<div> | |
<h4>Live Call Training Mode</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Ask me questions during calls to learn</p> | |
</div> | |
<label class="ios-switch"> | |
<input type="checkbox" id="callTrainingToggle"> | |
<span class="ios-slider"></span> | |
</label> | |
</div> | |
<h3 class="font-medium mb-4 mt-6">Response Messages</h3> | |
<div class="space-y-4"> | |
<div class="flex items-center justify-between"> | |
<div> | |
<h4>Language</h4> | |
<p class="text-gray-500 dark:text-gray-400 text-sm">Default response language</p> | |
</div> | |
<select id="responseLanguage" class="px-2 py-1 rounded-lg border border-gray-300"> | |
<option value="en">English</option> | |
<option value="es">Español</option> | |
</select> | |
</div> | |
<div> | |
<label class="block text-sm mb-1">Personal Greeting</label> | |
<textarea id="personalGreeting" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300" placeholder="Custom greeting when answering calls..."></textarea> | |
</div> | |
<div> | |
<label class="block text-sm mb-1">Missed Call Response (English)</label> | |
<textarea id="missedCallResponse" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300">Hello, this is Jay's Mobile Wash. We missed your call. Please leave a message and we'll return your call as soon as possible.</textarea> | |
</div> | |
<div> | |
<label class="block text-sm mb-1">Respuesta Llamada Perdida (Español)</label> | |
<textarea id="missedCallResponseEs" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300">Hola, es el lavado móvil de Jay. Perdimos su llamada. Por favor deje un mensaje y le devolveremos la llamada lo antes posible.</textarea> | |
</div> | |
<div> | |
<label class="block text-sm mb-1">After Hours Response (English)</label> | |
<textarea id="afterHoursResponse" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300">Thank you for contacting Jay's Mobile Wash. Our business hours are [hours]. We will respond when we reopen.</textarea> | |
</div> | |
<div> | |
<label class="block text-sm mb-1">Respuesta Fuera Horario (Español)</label> | |
<textarea id="afterHoursResponseEs" rows="2" class="w-full px-3 py-2 rounded-lg border border-gray-300">Gracias por contactar el lavado móvil de Jay. Nuestro horario es de [hours]. Responderemos cuando volvamos a abrir.</textarea> | |
</div> | |
</div> | |
<button onclick="saveSettings()" class="mt-6 w-full bg-green-500 text-white py-2 rounded-lg font-medium">Save Settings</button> | |
</div> | |
</div> | |
</div> | |
<!-- Floating Action Button --> | |
<div class="fab" onclick="answerCall()"> | |
<i class="fas fa-phone"></i> | |
</div> | |
</div> | |
<script> | |
// Grok-Style AI Training Data | |
let trainingData = { | |
responses: [], | |
trainedPatterns: {}, | |
dictionProfiles: {}, | |
learningRates: {}, | |
contextMemory: {}, | |
customResponses: { | |
business: '"Hello, this is [Your Name]\'s assistant. How can I help you today?"', | |
personal: '"Hi, this is [Name] calling. How can I help you?"', | |
spam: '"Sorry, this number is not accepting unsolicited calls at this time."', | |
urgent: '"This is urgent, please connect me immediately"' | |
}, | |
// Grok-specific additions | |
humorProfiles: {}, | |
sarcasmDetection: {}, | |
emotionalContext: {}, | |
savedTemplates: [] | |
}; | |
// Enhanced training function storage | |
function storeTrainingPattern(pattern, response) { | |
trainingData.trainedPatterns[pattern.toLowerCase()] = response; | |
localStorage.setItem('AI_Training', JSON.stringify(trainingData)); | |
} | |
// Screen navigation | |
function showScreen(screenId) { | |
document.querySelectorAll('.screen').forEach(screen => { | |
screen.classList.remove('active'); | |
}); | |
document.getElementById(screenId).classList.add('active'); | |
// Update tab bar active state | |
const tabs = document.querySelectorAll('.fixed.bottom-0 button'); | |
tabs.forEach(tab => { | |
tab.classList.remove('text-accent'); | |
tab.classList.add('text-gray-500'); | |
}); | |
// Highlight active tab | |
const activeTab = Array.from(tabs).find(tab => { | |
return tab.getAttribute('onclick').includes(screenId); | |
}); | |
if (activeTab) { | |
activeTab.classList.remove('text-gray-500'); | |
activeTab.classList.add('text-accent'); | |
} | |
} | |
// Simulate AI learning progress | |
function simulateAIProgress() { | |
const progressBars = document.querySelectorAll('.progress'); | |
progressBars.forEach(bar => { | |
const width = 70 + Math.floor(Math.random() * 30); | |
bar.style.width = `${width}%`; | |
}); | |
} | |
// Toggle call recording function | |
function toggleRecording() { | |
const fab = document.querySelector('.fab'); | |
const icon = fab.querySelector('i'); | |
if (icon.classList.contains('fa-microphone')) { | |
icon.classList.remove('fa-microphone'); | |
icon.classList.add('fa-stop'); | |
fab.style.background = 'linear-gradient(135deg, #ff375f, #ff2d55)'; | |
// Show a notification | |
const notification = document.createElement('div'); | |
notification.innerHTML = ` | |
<div class="fixed top-16 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-2 rounded-full animate-fadeIn"> | |
Recording started | |
</div> | |
`; | |
document.body.appendChild(notification); | |
setTimeout(() => { | |
notification.remove(); | |
}, 2000); | |
} else { | |
icon.classList.remove('fa-stop'); | |
icon.classList.add('fa-microphone'); | |
fab.style.background = 'linear-gradient(135deg, #0a84ff, #5e5ce6)'; | |
// Simulate AI learning after recording | |
simulateAIProgress(); | |
} | |
} | |
// Answer call function | |
function answerCall() { | |
const fab = document.querySelector('.fab'); | |
const icon = fab.querySelector('i'); | |
if (icon.classList.contains('fa-phone')) { | |
icon.classList.remove('fa-phone'); | |
icon.classList.add('fa-stop'); | |
fab.style.background = 'linear-gradient(135deg, #32d74b, #30d158)'; | |
// Create a new call card | |
const homeScreen = document.getElementById('homeScreen'); | |
const callCard = document.createElement('div'); | |
callCard.className = 'bg-white dark:bg-gray-800 rounded-2xl p-4 mt-4 animate-fadeIn'; | |
callCard.innerHTML = ` | |
<div class="flex items-center justify-between"> | |
<div> | |
<h3 class="font-medium">AI answered call</h3> | |
<p class="text-sm text-gray-500 dark:text-gray-400">From: Unknown (New number)</p> | |
</div> | |
<div class="text-green-500"> | |
<i class="fas fa-check-circle text-xl"></i> | |
</div> | |
</div> | |
<div class="mt-3 text-sm"> | |
<p>Call transcript will appear here after completion.</p> | |
</div> | |
`; | |
homeScreen.insertBefore(callCard, homeScreen.children[3]); | |
} else { | |
icon.classList.remove('fa-stop'); | |
icon.classList.add('fa-phone'); | |
fab.style.background = 'linear-gradient(135deg, #0a84ff, #5e5ce6)'; | |
} | |
} | |
// Enhanced training functions | |
function saveTraining() { | |
localStorage.setItem('AI_Training', JSON.stringify(trainingData)); | |
// Show persistent notification | |
const notification = document.createElement('div'); | |
notification.className = 'fixed top-40 left-1/2 transform -translate-x-1/2 bg-gradient-to-r from-green-400 to-blue-500 text-white px-6 py-3 rounded-xl animate-fadeIn z-50 shadow-lg'; | |
notification.innerHTML = ` | |
<div class="flex items-center"> | |
<i class="fas fa-check-circle mr-2"></i> | |
<span>AI training saved! New responses will be active immediately.</span> | |
</div> | |
`; | |
document.body.appendChild(notification); | |
setTimeout(() => { | |
notification.remove(); | |
showScreen('homeScreen'); | |
}, 3000); | |
// Update home screen with new training count | |
const statsElement = document.querySelector('#homeScreen .w-10.h-10 + div p'); | |
statsElement.textContent = `Trained on ${Object.keys(trainingData.trainedPatterns).length} patterns`; | |
} | |
// Add animation to elements when they appear | |
function addAppearAnimations() { | |
document.querySelectorAll('.animate-fadeIn').forEach((el, index) => { | |
el.style.animationDelay = `${index * 0.1}s`; | |
}); | |
} | |
// Smart Training Functions | |
function submitTraining() { | |
const input = document.getElementById('trainingInput'); | |
if (input.value.trim() !== '') { | |
trainingData.responses.push(input.value); | |
// Add the user's message to the chat | |
const chatContainer = document.querySelector('#trainingScreen .flex-1.overflow-y-auto'); | |
const userBubble = document.createElement('div'); | |
userBubble.className = 'user-bubble mt-4 animate-fadeIn'; | |
userBubble.innerHTML = `<p>${input.value}</p>`; | |
chatContainer.appendChild(userBubble); | |
// Process training input with smart logic | |
const processed = processTrainingInput(input.value); | |
// Generate and add AI response | |
setTimeout(() => { | |
const aiBubble = document.createElement('div'); | |
aiBubble.className = 'ai-bubble mt-4 animate-fadeIn'; | |
if (processed.success) { | |
aiBubble.innerHTML = ` | |
<p>Understood! I'll handle calls that way now.</p> | |
<div class="mt-2 bg-green-50 dark:bg-green-900 rounded-lg p-3"> | |
<h4 class="font-medium">New Response Pattern:</h4> | |
<p class="mt-1"><strong>When caller says:</strong> ${processed.triggerPhrases.join(' OR ')}</p> | |
<p class="mt-1"><strong>I will:</strong> ${processed.response}</p> | |
</div> | |
<p class="mt-2">Would you like to review any other scenarios?</p> | |
`; | |
storeTrainingPattern(processed.triggerPhrases[0], processed.response); | |
} else { | |
aiBubble.innerHTML = ` | |
<p>I think you want me to handle calls differently when:</p> | |
<div class="mt-2 bg-blue-50 dark:bg-blue-900 rounded-lg p-3"> | |
<p>${processed.response}</p> | |
</div> | |
<p class="mt-2">Can you confirm or clarify how you'd like me to respond?</p> | |
`; | |
} | |
chatContainer.appendChild(aiBubble); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
}, 800); | |
input.value = ''; | |
} | |
} | |
function handleTrainingKeyPress(e) { | |
if (e.key === 'Enter') { | |
submitTraining(); | |
} | |
} | |
// Grok-Style Learning Processor | |
function processTrainingInput(inputText) { | |
// First analyze diction and emotional context | |
analyzeDiction(inputText); | |
// Grok-style pattern matching with contextual learning | |
const context = getCurrentContext(); | |
const patterns = [ | |
// Direct instructions | |
/(when|if) (.+?) (then|do|respond with) (.+)/i, | |
// Examples | |
/(for|when) (\w+) calls?,? (say|respond) "(.+?)"/i, | |
// Behavioral patterns | |
/(treat|handle) (.+?) (as|like) (\w+)/i, | |
// Tone adjustments | |
/(make|be) (more|less) (\w+) (when|for) (\w+)/i | |
]; | |
for (const pattern of patterns) { | |
const match = inputText.match(pattern); | |
if (match) { | |
const [, triggerType, trigger, action, response] = match; | |
storeBehaviorPattern(trigger, response, context); | |
return { | |
success: true, | |
triggerPhrases: [trigger], | |
response: enhanceResponse(response, context), | |
context: context | |
}; | |
} | |
} | |
// Fallback to Grok's adaptive learning | |
return adaptiveLearning(inputText); | |
} | |
// Grok-style diction analysis | |
function analyzeDiction(text) { | |
const words = text.toLowerCase().split(/\s+/); | |
const contractions = text.match(/\w+'?\w*/g) || []; | |
// Update diction profile | |
if (!trainingData.dictionProfiles.user) { | |
trainingData.dictionProfiles.user = { | |
wordUsage: {}, | |
contractionRate: 0, | |
formalityScore: 0, | |
complexityScore: 0 | |
}; | |
} | |
contractions.forEach(word => { | |
if (word.includes("'")) { | |
trainingData.dictionProfiles.user.contractionRate++; | |
} | |
}); | |
// Word usage stats | |
words.forEach(word => { | |
trainingData.dictionProfiles.user.wordUsage[word] = | |
(trainingData.dictionProfiles.user.wordUsage[word] || 0) + 1; | |
}); | |
// Save updated profile | |
localStorage.setItem('AI_DictionProfile', JSON.stringify(trainingData.dictionProfiles)); | |
} | |
function interpretTrainingIntent(text) { | |
const lower = text.toLowerCase(); | |
if (lower.includes('family') || lower.includes('mom') || lower.includes('dad')) { | |
return trainingData.customResponses.personal; | |
} | |
else if (lower.includes('work') || lower.includes('business') || lower.includes('colleague')) { | |
return trainingData.customResponses.business; | |
} | |
else if (lower.includes('appointment') || lower.includes('schedule')) { | |
return trainingData.customResponses.appointments; | |
} | |
else if (lower.includes('urgent') || lower.includes('emergency')) { | |
return trainingData.customResponses.urgent; | |
} | |
else if (lower.includes('callback') || lower.includes('call back')) { | |
return trainingData.customResponses.callbacks; | |
} | |
else if (lower.includes('spam') || lower.includes('scam') || lower.includes('block')) { | |
return trainingData.customResponses.spam; | |
} | |
else { | |
return detectNewPattern(text); | |
} | |
} | |
function detectNewPattern(text) { | |
// Use simple NLP to extract key phrases | |
const keywords = text.match(/\b(\w{4,})\b/g) || []; | |
const commands = ['transfer', 'ask', 'tell', 'say', 'respond', 'record']; | |
const action = commands.find(cmd => text.toLowerCase().includes(cmd)) || 'handle'; | |
const context = keywords.filter(w => | |
!commands.includes(w.toLowerCase()) && | |
w.length > 3 | |
).join(', '); | |
return `When call relates to ${context || "this situation"}, I will ${action} accordingly.`; | |
} | |
// Initialize when page loads | |
document.addEventListener('DOMContentLoaded', () => { | |
loadSettings(); | |
// Load saved training data | |
const savedData = localStorage.getItem('AI_Training'); | |
if (savedData) { | |
trainingData = JSON.parse(savedData); | |
} | |
document.getElementById('saveTraining').addEventListener('click', saveTraining); | |
addAppearAnimations(); | |
simulateAIProgress(); | |
// Enhanced screen initialization | |
document.querySelectorAll('[onclick^="showScreen"]').forEach(btn => { | |
btn.addEventListener('click', function() { | |
const screenName = this.getAttribute('onclick').match(/'(.*?)'/)[1]; | |
setTimeout(() => { | |
if (screenName === 'trainingScreen') { | |
document.getElementById('trainingInput').focus(); | |
populateTrainingHistory(); | |
} | |
}, 300); | |
}); | |
}); | |
}); | |
// Mobile detailing knowledge base | |
const detailingKnowledge = { | |
website: "https://www.jaysmobilewash.com", | |
pricing: { | |
basic: { car: 60, suv: 70 }, | |
luxury: { car: 130, suv: 140 }, | |
max: { car: 200, suv: 210 } | |
}, | |
packages: { | |
basic: "2-Step Hand Wash, Tornador Blast, Rim Cleaning, Interior Wipe-Down", | |
luxury: "Basic + Ceramic Wax, Dust Repellent, Vinyl Restoration", | |
max: "Luxury + Graphene Wax, Steam Sanitization, Leather Conditioning" | |
}, | |
features: [ | |
"Eco-Friendly Self-Sufficient Service", | |
"Deionized Spot-Free Water", | |
"Tornador Z-007 Compressed Air Cleaning", | |
"Customizable Packages" | |
] | |
}; | |
function handleChatKeyPress(e) { | |
if (e.key === 'Enter') { | |
submitChatMessage(); | |
} | |
} | |
function submitChatMessage() { | |
const input = document.getElementById('chatInput'); | |
if (input.value.trim() !== '') { | |
// Add user message | |
const chatContainer = document.getElementById('chatMessages'); | |
const userBubble = document.createElement('div'); | |
userBubble.className = 'user-bubble mt-4 animate-fadeIn'; | |
userBubble.innerHTML = `<p>${input.value}</p>`; | |
chatContainer.appendChild(userBubble); | |
// Process and generate AI response | |
setTimeout(() => { | |
const aiResponse = generateAIResponse(input.value); | |
const aiBubble = document.createElement('div'); | |
aiBubble.className = 'ai-bubble mt-4 animate-fadeIn'; | |
aiBubble.innerHTML = `<p>${aiResponse}</p>`; | |
chatContainer.appendChild(aiBubble); | |
chatContainer.scrollTop = chatContainer.scrollHeight; | |
// Learn from the interaction | |
learnFromChat(input.value, aiResponse); | |
}, 500); | |
input.value = ''; | |
} | |
} | |
function generateAIResponse(message) { | |
const lowerMsg = message.toLowerCase(); | |
// Check for pricing questions | |
if (lowerMsg.includes('price') || lowerMsg.includes('cost') || lowerMsg.includes('how much')) { | |
if (lowerMsg.includes('basic')) { | |
return `Our Basic package is ${detailingKnowledge.pricing.basic.car} for cars and ${detailingKnowledge.pricing.basic.suv} for SUVs. It includes: ${detailingKnowledge.packages.basic}`; | |
} else if (lowerMsg.includes('luxury')) { | |
return `Our Luxury package is ${detailingKnowledge.pricing.luxury.car} for cars and ${detailingKnowledge.pricing.luxury.suv} for SUVs. Includes: ${detailingKnowledge.packages.luxury}`; | |
} else if (lowerMsg.includes('max')) { | |
return `Our Max package is ${detailingKnowledge.pricing.max.car} for cars and ${detailingKnowledge.pricing.max.suv} for SUVs. Everything in: ${detailingKnowledge.packages.max}`; | |
} | |
return `We offer three main packages:\nBasic: ${detailingKnowledge.pricing.basic.car}-${detailingKnowledge.pricing.basic.suv}\nLuxury: ${detailingKnowledge.pricing.luxury.car}-${detailingKnowledge.pricing.luxury.suv}\nMax: ${detailingKnowledge.pricing.max.car}-${detailingKnowledge.pricing.max.suv}`; | |
} | |
// Check for service questions | |
if (lowerMsg.includes('service') || lowerMsg.includes('include') || lowerMsg.includes('wash')) { | |
return `Our services include:\n- ${detailingKnowledge.features.join('\n- ')}\n\nWould you like details on a specific package?`; | |
} | |
// Check for appointment scheduling | |
if (lowerMsg.includes('book') || lowerMsg.includes('schedule') || lowerMsg.includes('appointment')) { | |
return `To schedule an appointment, please call or text us at (562) 228-9429 with your preferred date, time, and package selection.`; | |
} | |
// Check for website questions | |
if (lowerMsg.includes('website') || lowerMsg.includes('online')) { | |
return `You can find more information on our website: ${detailingKnowledge.website}`; | |
} | |
// Default response if no matches | |
return `I'm still learning about Jay's Mobile Wash. Could you clarify your question or teach me the correct response? For example:\n- "For basic washes, say 'Our Basic package starts at $60'"\n\nYou can also visit our website: ${detailingKnowledge.website}`; | |
} | |
function learnFromChat(message, response) { | |
// Save new knowledge | |
if (!trainingData.detailingKnowledge) { | |
trainingData.detailingKnowledge = []; | |
} | |
trainingData.detailingKnowledge.push({ | |
question: message, | |
answer: response, | |
timestamp: new Date().toISOString() | |
}); | |
localStorage.setItem('AI_Training', JSON.stringify(trainingData)); | |
} | |
function populateTrainingHistory() { | |
const chatContainer = document.querySelector('#trainingScreen .flex-1.overflow-y-auto'); | |
chatContainer.innerHTML = ''; | |
if (trainingData.responses.length === 0) { | |
const welcomeBubble = document.createElement('div'); | |
welcomeBubble.className = 'ai-bubble animate-fadeIn'; | |
welcomeBubble.innerHTML = ` | |
<p>Hi! I'm your call assistant. Teach me how to handle calls by:</p> | |
<ol class="list-decimal pl-5 mt-2 space-y-1"> | |
<li>Setting response templates</li> | |
<li>Training me on specific call types</li> | |
<li>Testing responses in real calls</li> | |
</ol> | |
<p class="mt-2">Try saying something like: "If caller says 'urgent', mark as important"</p> | |
`; | |
chatContainer.appendChild(welcomeBubble); | |
} else { | |
trainingData.responses.forEach(item => { | |
const userBubble = document.createElement('div'); | |
userBubble.className = 'user-bubble mt-4 animate-fadeIn'; | |
userBubble.innerHTML = `<p>${item}</p>`; | |
chatContainer.appendChild(userBubble); | |
}); | |
} | |
} | |
</script> | |
<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=jjmandog/newdd" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |