call-genie / index.html
ebonivon's picture
Build a fully functional AI-powered web application named "CallGenie" that enables users to create, customize, and deploy their own AI calling agents (similar to OmniDim). The app should feature an immersive 3D user interface for an engaging experience and a robust backend integrating the Gemini AI API key for advanced conversational AI capabilities. --- Requirements: Frontend: Use React.js with Three.js or React Three Fiber for creating a smooth, interactive 3D interface (like a rotating agent avatar or 3D dashboard) Responsive design for desktop and mobile Agent creation wizard UI allowing users to: Choose voice type, language, and personality traits Script or customize dialogue flows with a visual flowchart or form inputs Test calls in real-time with AI-generated responses Real-time call simulation with audio playback using text-to-speech powered by Gemini API Dashboard for managing multiple agents, viewing call logs, and analytics User authentication (email/password or OAuth) for saving agents and data securely Backend: Build with Node.js and Express.js (or your preferred backend stack) Securely handle Gemini API key to communicate with Gemini AI models for: Natural language understanding & response generation Text-to-speech synthesis for voice calls API endpoints for: Creating/updating/deleting AI agents and their scripts Handling real-time call simulation and streaming responses User authentication and data persistence Use a database (MongoDB/PostgreSQL) for storing user data, agent configs, and call logs Implement websocket or server-sent events for real-time interaction during calls Additional: Error handling and loading states for smooth UX Include environment variable setup instructions for Gemini API key Deployable on platforms like Vercel (frontend) and Railway/Heroku (backend) Clear README with setup, usage, and deployment steps At the bottom of the app, include: "© 2025 OrionixLabs. All rights reserved." --- Bonus: Animate the 3D agent with subtle facial expressions synced to AI responses Include multilingual support in UI and AI conversations Add voice input option to simulate full duplex calls --- - Initial Deployment
c310226 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CallGenie - AI Calling Agents</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.net.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.agent-avatar {
transition: all 0.3s ease;
}
.agent-avatar:hover {
transform: scale(1.05);
}
.flowchart-node {
position: relative;
padding: 10px;
border-radius: 8px;
background: #3b82f6;
color: white;
margin: 10px;
cursor: pointer;
transition: all 0.2s;
}
.flowchart-node:hover {
background: #2563eb;
transform: translateY(-2px);
}
.flowchart-connector {
position: absolute;
bottom: -10px;
left: 50%;
width: 2px;
height: 20px;
background: #94a3b8;
}
.call-bubble {
max-width: 70%;
padding: 12px 16px;
border-radius: 18px;
margin: 8px 0;
position: relative;
}
.user-bubble {
background: #3b82f6;
color: white;
align-self: flex-end;
border-bottom-right-radius: 4px;
}
.agent-bubble {
background: #e2e8f0;
color: #1e293b;
align-self: flex-start;
border-bottom-left-radius: 4px;
}
#agentCanvas {
width: 100%;
height: 300px;
background: transparent;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.voice-wave {
height: 4px;
background: #3b82f6;
border-radius: 2px;
animation: wave 1.5s infinite ease-in-out;
}
@keyframes wave {
0%, 100% { transform: scaleY(1); }
50% { transform: scaleY(0.3); }
}
</style>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col">
<!-- Background Animation -->
<div id="vanta-bg" class="fixed top-0 left-0 w-full h-full -z-10"></div>
<!-- Header -->
<header class="bg-white bg-opacity-90 shadow-sm">
<div class="container mx-auto px-4 py-4 flex justify-between items-center">
<div class="flex items-center space-x-2">
<i class="fas fa-robot text-3xl text-blue-500"></i>
<h1 class="text-2xl font-bold text-gray-800">CallGenie</h1>
</div>
<nav class="hidden md:flex space-x-6">
<a href="#dashboard" class="text-gray-700 hover:text-blue-500 font-medium">Dashboard</a>
<a href="#create" class="text-gray-700 hover:text-blue-500 font-medium">Create Agent</a>
<a href="#analytics" class="text-gray-700 hover:text-blue-500 font-medium">Analytics</a>
</nav>
<div class="flex items-center space-x-4">
<button id="loginBtn" class="px-4 py-2 rounded-full bg-blue-500 text-white hover:bg-blue-600 transition">Login</button>
<button class="md:hidden" id="mobileMenuBtn">
<i class="fas fa-bars text-xl text-gray-700"></i>
</button>
</div>
</div>
<!-- Mobile Menu -->
<div id="mobileMenu" class="hidden bg-white py-2 px-4 shadow-md">
<a href="#dashboard" class="block py-2 text-gray-700 hover:text-blue-500">Dashboard</a>
<a href="#create" class="block py-2 text-gray-700 hover:text-blue-500">Create Agent</a>
<a href="#analytics" class="block py-2 text-gray-700 hover:text-blue-500">Analytics</a>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow container mx-auto px-4 py-8">
<!-- Dashboard Section -->
<section id="dashboard" class="mb-12">
<h2 class="text-3xl font-bold text-gray-800 mb-6">Your AI Agents</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Agent Card 1 -->
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition">
<div class="p-4">
<div class="flex items-center space-x-4 mb-4">
<div class="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center">
<i class="fas fa-headset text-2xl text-blue-500"></i>
</div>
<div>
<h3 class="font-bold text-lg text-gray-800">Customer Support Bot</h3>
<p class="text-gray-500 text-sm">Active • 12 calls today</p>
</div>
</div>
<div class="flex justify-between items-center">
<div class="flex space-x-2">
<span class="px-2 py-1 bg-green-100 text-green-800 text-xs rounded-full">English</span>
<span class="px-2 py-1 bg-purple-100 text-purple-800 text-xs rounded-full">Friendly</span>
</div>
<button class="px-3 py-1 bg-blue-500 text-white rounded-full text-sm hover:bg-blue-600">Manage</button>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 flex justify-between items-center">
<div class="text-sm text-gray-600">
<i class="fas fa-chart-line mr-1"></i> 87% success rate
</div>
<button class="text-blue-500 text-sm font-medium hover:text-blue-700">
View Logs <i class="fas fa-chevron-right ml-1"></i>
</button>
</div>
</div>
<!-- Agent Card 2 -->
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition">
<div class="p-4">
<div class="flex items-center space-x-4 mb-4">
<div class="w-16 h-16 rounded-full bg-purple-100 flex items-center justify-center">
<i class="fas fa-briefcase text-2xl text-purple-500"></i>
</div>
<div>
<h3 class="font-bold text-lg text-gray-800">Sales Assistant</h3>
<p class="text-gray-500 text-sm">Active • 5 calls today</p>
</div>
</div>
<div class="flex justify-between items-center">
<div class="flex space-x-2">
<span class="px-2 py-1 bg-green-100 text-green-800 text-xs rounded-full">Spanish</span>
<span class="px-2 py-1 bg-purple-100 text-purple-800 text-xs rounded-full">Persuasive</span>
</div>
<button class="px-3 py-1 bg-blue-500 text-white rounded-full text-sm hover:bg-blue-600">Manage</button>
</div>
</div>
<div class="bg-gray-50 px-4 py-3 flex justify-between items-center">
<div class="text-sm text-gray-600">
<i class="fas fa-chart-line mr-1"></i> 92% success rate
</div>
<button class="text-blue-500 text-sm font-medium hover:text-blue-700">
View Logs <i class="fas fa-chevron-right ml-1"></i>
</button>
</div>
</div>
<!-- Add New Agent Card -->
<div class="bg-white rounded-xl shadow-md overflow-hidden hover:shadow-lg transition border-2 border-dashed border-gray-300 flex items-center justify-center">
<button id="createNewAgentBtn" class="p-8 text-center">
<div class="w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center mx-auto mb-4">
<i class="fas fa-plus text-2xl text-gray-500"></i>
</div>
<h3 class="font-bold text-lg text-gray-700">Create New Agent</h3>
<p class="text-gray-500 text-sm">Build your custom AI calling agent</p>
</button>
</div>
</div>
</section>
<!-- Create Agent Section (Hidden by default) -->
<section id="createAgentSection" class="hidden mb-12 bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Create New AI Agent</h2>
<button id="closeCreateAgentBtn" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<!-- Creation Wizard -->
<div class="flex flex-col md:flex-row gap-6">
<!-- Left Side - Agent Preview -->
<div class="md:w-1/3">
<div class="bg-gray-50 rounded-lg p-6 mb-6">
<h3 class="font-medium text-gray-700 mb-4">Agent Preview</h3>
<div id="agentCanvas" class="mb-4"></div>
<div class="text-center">
<h4 id="previewAgentName" class="font-bold text-lg text-gray-800">New Agent</h4>
<p id="previewAgentRole" class="text-gray-500 text-sm">AI Calling Agent</p>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-6">
<h3 class="font-medium text-gray-700 mb-4">Voice Preview</h3>
<div class="flex items-center justify-between mb-4">
<div>
<p id="previewVoiceType" class="font-medium">Standard Female</p>
<p class="text-gray-500 text-sm">English (US)</p>
</div>
<button id="testVoiceBtn" class="p-2 rounded-full bg-blue-500 text-white hover:bg-blue-600">
<i class="fas fa-play"></i>
</button>
</div>
<div class="flex space-x-1 h-4">
<div class="voice-wave w-1"></div>
<div class="voice-wave w-1" style="animation-delay: 0.2s"></div>
<div class="voice-wave w-1" style="animation-delay: 0.4s"></div>
<div class="voice-wave w-1" style="animation-delay: 0.6s"></div>
<div class="voice-wave w-1" style="animation-delay: 0.8s"></div>
</div>
</div>
</div>
<!-- Right Side - Configuration -->
<div class="md:w-2/3">
<!-- Wizard Tabs -->
<div class="flex border-b border-gray-200 mb-6">
<button class="wizard-tab py-2 px-4 font-medium text-blue-500 border-b-2 border-blue-500" data-tab="basic">Basic Info</button>
<button class="wizard-tab py-2 px-4 font-medium text-gray-500" data-tab="voice">Voice & Language</button>
<button class="wizard-tab py-2 px-4 font-medium text-gray-500" data-tab="script">Scripting</button>
<button class="wizard-tab py-2 px-4 font-medium text-gray-500" data-tab="advanced">Advanced</button>
</div>
<!-- Tab Contents -->
<div class="wizard-content">
<!-- Basic Info Tab -->
<div id="basic-tab" class="tab-content active">
<div class="mb-4">
<label for="agentName" class="block text-sm font-medium text-gray-700 mb-1">Agent Name</label>
<input type="text" id="agentName" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="e.g. Customer Support Bot">
</div>
<div class="mb-4">
<label for="agentRole" class="block text-sm font-medium text-gray-700 mb-1">Agent Role</label>
<input type="text" id="agentRole" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="e.g. Customer Support, Sales Assistant">
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Personality Traits</label>
<div class="flex flex-wrap gap-2">
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="personality" value="friendly">
<span class="ml-2 text-sm">Friendly</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="personality" value="professional">
<span class="ml-2 text-sm">Professional</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="personality" value="enthusiastic">
<span class="ml-2 text-sm">Enthusiastic</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="personality" value="calm">
<span class="ml-2 text-sm">Calm</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="personality" value="persuasive">
<span class="ml-2 text-sm">Persuasive</span>
</label>
</div>
</div>
<div class="mb-4">
<label for="agentDescription" class="block text-sm font-medium text-gray-700 mb-1">Description</label>
<textarea id="agentDescription" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Describe your agent's purpose and behavior"></textarea>
</div>
</div>
<!-- Voice & Language Tab -->
<div id="voice-tab" class="tab-content">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Voice Type</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="flex items-center p-3 border border-gray-300 rounded-md cursor-pointer">
<input type="radio" name="voiceType" class="h-4 w-4 text-blue-500" value="standard-female" checked>
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Standard Female</span>
<span class="block text-xs text-gray-500">Natural, clear voice</span>
</div>
</label>
</div>
<div>
<label class="flex items-center p-3 border border-gray-300 rounded-md cursor-pointer">
<input type="radio" name="voiceType" class="h-4 w-4 text-blue-500" value="standard-male">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Standard Male</span>
<span class="block text-xs text-gray-500">Warm, professional tone</span>
</div>
</label>
</div>
<div>
<label class="flex items-center p-3 border border-gray-300 rounded-md cursor-pointer">
<input type="radio" name="voiceType" class="h-4 w-4 text-blue-500" value="youthful-female">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Youthful Female</span>
<span class="block text-xs text-gray-500">Energetic and friendly</span>
</div>
</label>
</div>
<div>
<label class="flex items-center p-3 border border-gray-300 rounded-md cursor-pointer">
<input type="radio" name="voiceType" class="h-4 w-4 text-blue-500" value="authoritative-male">
<div class="ml-3">
<span class="block text-sm font-medium text-gray-700">Authoritative Male</span>
<span class="block text-xs text-gray-500">Confident and strong</span>
</div>
</label>
</div>
</div>
</div>
<div class="mb-4">
<label for="language" class="block text-sm font-medium text-gray-700 mb-1">Language</label>
<select id="language" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="en-US">English (US)</option>
<option value="en-GB">English (UK)</option>
<option value="es-ES">Spanish (Spain)</option>
<option value="fr-FR">French (France)</option>
<option value="de-DE">German (Germany)</option>
<option value="it-IT">Italian (Italy)</option>
<option value="pt-BR">Portuguese (Brazil)</option>
<option value="ja-JP">Japanese</option>
<option value="zh-CN">Chinese (Mandarin)</option>
</select>
</div>
<div class="mb-4">
<label for="speechRate" class="block text-sm font-medium text-gray-700 mb-1">Speech Rate</label>
<input type="range" id="speechRate" min="0.5" max="2" step="0.1" value="1" class="w-full">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>Slower</span>
<span>Normal</span>
<span>Faster</span>
</div>
</div>
<div class="mb-4">
<label for="pitch" class="block text-sm font-medium text-gray-700 mb-1">Pitch</label>
<input type="range" id="pitch" min="0.5" max="1.5" step="0.1" value="1" class="w-full">
<div class="flex justify-between text-xs text-gray-500 mt-1">
<span>Lower</span>
<span>Normal</span>
<span>Higher</span>
</div>
</div>
</div>
<!-- Scripting Tab -->
<div id="script-tab" class="tab-content">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Script Type</label>
<div class="flex space-x-4">
<label class="inline-flex items-center">
<input type="radio" name="scriptType" class="h-4 w-4 text-blue-500" value="guided" checked>
<span class="ml-2 text-sm">Guided Conversation</span>
</label>
<label class="inline-flex items-center">
<input type="radio" name="scriptType" class="h-4 w-4 text-blue-500" value="freeform">
<span class="ml-2 text-sm">Freeform AI</span>
</label>
</div>
</div>
<div id="guidedScriptSection">
<div class="mb-4">
<label for="greeting" class="block text-sm font-medium text-gray-700 mb-1">Greeting Message</label>
<textarea id="greeting" rows="2" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Hello! This is [Agent Name] from [Your Company]. How can I help you today?"></textarea>
</div>
<div class="mb-4">
<label for="commonQuestions" class="block text-sm font-medium text-gray-700 mb-1">Common Questions & Responses</label>
<div class="space-y-2">
<div class="flex items-start space-x-2">
<input type="text" class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Question">
<input type="text" class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Response">
<button class="px-2 py-2 text-gray-500 hover:text-red-500">
<i class="fas fa-times"></i>
</button>
</div>
<button class="text-blue-500 text-sm flex items-center">
<i class="fas fa-plus mr-1"></i> Add another question
</button>
</div>
</div>
<div class="mb-4">
<label for="closing" class="block text-sm font-medium text-gray-700 mb-1">Closing Message</label>
<textarea id="closing" rows="2" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Thank you for calling. Have a great day!"></textarea>
</div>
</div>
<div id="freeformScriptSection" class="hidden">
<div class="bg-yellow-50 border-l-4 border-yellow-400 p-4 mb-4">
<div class="flex">
<div class="flex-shrink-0">
<i class="fas fa-exclamation-circle text-yellow-400"></i>
</div>
<div class="ml-3">
<p class="text-sm text-yellow-700">
Freeform AI mode uses Gemini's advanced conversational AI without predefined scripts. You can still provide guidelines below.
</p>
</div>
</div>
</div>
<div class="mb-4">
<label for="aiGuidelines" class="block text-sm font-medium text-gray-700 mb-1">AI Guidelines</label>
<textarea id="aiGuidelines" rows="4" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Provide guidelines for how the AI should behave, topics to avoid, etc."></textarea>
</div>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Call Flow Preview</label>
<div class="bg-gray-50 rounded-lg p-4">
<div class="flowchart-node">
<div class="flex items-center">
<i class="fas fa-play-circle mr-2"></i>
<span>Start Call</span>
</div>
<div class="flowchart-connector"></div>
</div>
<div class="flowchart-node">
<div class="flex items-center">
<i class="fas fa-comment mr-2"></i>
<span>Play Greeting</span>
</div>
<div class="flowchart-connector"></div>
</div>
<div class="flowchart-node">
<div class="flex items-center">
<i class="fas fa-exchange-alt mr-2"></i>
<span>Conversation</span>
</div>
<div class="flowchart-connector"></div>
</div>
<div class="flowchart-node">
<div class="flex items-center">
<i class="fas fa-stop-circle mr-2"></i>
<span>End Call</span>
</div>
</div>
</div>
</div>
</div>
<!-- Advanced Tab -->
<div id="advanced-tab" class="tab-content">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-1">Call Handling</label>
<div class="space-y-2">
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="callHandling" value="voicemail" checked>
<span class="ml-2 text-sm">Allow leaving voicemail if agent can't answer</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="callHandling" value="transfer" checked>
<span class="ml-2 text-sm">Allow transfer to human operator</span>
</label>
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500" name="callHandling" value="callback">
<span class="ml-2 text-sm">Offer callback option</span>
</label>
</div>
</div>
<div class="mb-4">
<label for="transferNumber" class="block text-sm font-medium text-gray-700 mb-1">Transfer Number</label>
<input type="text" id="transferNumber" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="+1 (555) 123-4567">
</div>
<div class="mb-4">
<label for="timeout" class="block text-sm font-medium text-gray-700 mb-1">Response Timeout (seconds)</label>
<input type="number" id="timeout" min="5" max="60" value="15" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="mb-4">
<label for="fallbackMessage" class="block text-sm font-medium text-gray-700 mb-1">Fallback Message</label>
<textarea id="fallbackMessage" rows="2" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="I didn't understand that. Could you please rephrase?"></textarea>
</div>
<div class="mb-4">
<label for="apiKey" class="block text-sm font-medium text-gray-700 mb-1">Gemini API Key (Optional)</label>
<input type="password" id="apiKey" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="sk-...">
<p class="text-xs text-gray-500 mt-1">Leave blank to use our shared key. For better performance, use your own Gemini API key.</p>
</div>
</div>
</div>
<!-- Navigation Buttons -->
<div class="flex justify-between mt-8">
<button id="prevTabBtn" class="px-4 py-2 text-gray-700 font-medium rounded-md border border-gray-300 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
<i class="fas fa-arrow-left mr-2"></i> Previous
</button>
<button id="nextTabBtn" class="px-4 py-2 bg-blue-500 text-white font-medium rounded-md hover:bg-blue-600">
Next <i class="fas fa-arrow-right ml-2"></i>
</button>
<button id="finishBtn" class="px-4 py-2 bg-green-500 text-white font-medium rounded-md hover:bg-green-600 hidden">
<i class="fas fa-check mr-2"></i> Finish & Create Agent
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Call Simulation Section -->
<section id="callSimulation" class="hidden mb-12 bg-white rounded-xl shadow-md overflow-hidden">
<div class="p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-bold text-gray-800">Call Simulation</h2>
<button id="closeCallSimulationBtn" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="flex flex-col md:flex-row gap-6">
<!-- Left Side - Agent Info -->
<div class="md:w-1/3">
<div class="bg-gray-50 rounded-lg p-6 mb-6">
<div class="flex items-center space-x-4 mb-4">
<div class="w-16 h-16 rounded-full bg-blue-100 flex items-center justify-center">
<i class="fas fa-headset text-2xl text-blue-500"></i>
</div>
<div>
<h3 id="simAgentName" class="font-bold text-lg text-gray-800">Customer Support Bot</h3>
<p id="simAgentRole" class="text-gray-500 text-sm">Customer Support</p>
</div>
</div>
<div class="space-y-2">
<div class="flex justify-between">
<span class="text-gray-600">Voice:</span>
<span id="simAgentVoice" class="font-medium">Standard Female</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Language:</span>
<span id="simAgentLanguage" class="font-medium">English (US)</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Status:</span>
<span class="text-green-500 font-medium">Ready</span>
</div>
</div>
</div>
<div class="bg-gray-50 rounded-lg p-6">
<h3 class="font-medium text-gray-700 mb-4">Call Controls</h3>
<div class="flex justify-center space-x-4 mb-4">
<button id="startCallBtn" class="w-16 h-16 rounded-full bg-green-500 text-white flex items-center justify-center hover:bg-green-600">
<i class="fas fa-phone text-xl"></i>
</button>
<button id="endCallBtn" class="w-16 h-16 rounded-full bg-red-500 text-white flex items-center justify-center hover:bg-red-600 opacity-50 cursor-not-allowed">
<i class="fas fa-phone-slash text-xl"></i>
</button>
</div>
<div class="flex items-center justify-center space-x-2">
<button class="p-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300">
<i class="fas fa-microphone"></i>
</button>
<button class="p-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300">
<i class="fas fa-volume-up"></i>
</button>
<button class="p-2 rounded-full bg-gray-200 text-gray-700 hover:bg-gray-300">
<i class="fas fa-cog"></i>
</button>
</div>
</div>
</div>
<!-- Right Side - Call Interface -->
<div class="md:w-2/3">
<div class="bg-gray-50 rounded-lg p-6 h-full">
<div id="callDisplay" class="flex flex-col items-center justify-center h-64">
<div class="text-center mb-4">
<i class="fas fa-phone-volume text-4xl text-gray-400 mb-2"></i>
<h3 class="text-xl font-medium text-gray-700">Ready to simulate call</h3>
<p class="text-gray-500">Click the green button to start</p>
</div>
</div>
<div id="callTranscript" class="hidden bg-white rounded-lg p-4 h-64 overflow-y-auto mb-4 flex flex-col">
<!-- Call transcript will appear here -->
</div>
<div id="callInputArea" class="hidden">
<div class="flex space-x-2">
<input type="text" id="callInput" class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Type your message...">
<button id="sendCallBtn" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">
<i class="fas fa-paper-plane"></i>
</button>
</div>
<div class="flex justify-center mt-2">
<button id="voiceInputBtn" class="px-3 py-1 text-sm text-blue-500 hover:text-blue-700">
<i class="fas fa-microphone mr-1"></i> Use Voice Input
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Analytics Section -->
<section id="analytics" class="mb-12">
<h2 class="text-3xl font-bold text-gray-800 mb-6">Call Analytics</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<!-- Stats Card 1 -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">Total Calls</p>
<h3 class="text-2xl font-bold text-gray-800 mt-1">1,248</h3>
</div>
<div class="p-3 rounded-full bg-blue-100 text-blue-500">
<i class="fas fa-phone text-xl"></i>
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-green-500">
<i class="fas fa-arrow-up mr-1"></i>
<span>12.5% increase from last week</span>
</div>
</div>
</div>
<!-- Stats Card 2 -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">Success Rate</p>
<h3 class="text-2xl font-bold text-gray-800 mt-1">89.2%</h3>
</div>
<div class="p-3 rounded-full bg-green-100 text-green-500">
<i class="fas fa-check-circle text-xl"></i>
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-green-500">
<i class="fas fa-arrow-up mr-1"></i>
<span>3.1% improvement</span>
</div>
</div>
</div>
<!-- Stats Card 3 -->
<div class="bg-white rounded-xl shadow-md p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium text-gray-500">Avg. Duration</p>
<h3 class="text-2xl font-bold text-gray-800 mt-1">2:45</h3>
</div>
<div class="p-3 rounded-full bg-purple-100 text-purple-500">
<i class="fas fa-clock text-xl"></i>
</div>
</div>
<div class="mt-4">
<div class="flex items-center text-sm text-red-500">
<i class="fas fa-arrow-down mr-1"></i>
<span>0:22 decrease</span>
</div>
</div>
</div>
</div>
<!-- Charts -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-xl shadow-md p-6">
<h3 class="text-lg font-medium text-gray-800 mb-4">Call Volume</h3>
<div class="h-64">
<canvas id="callVolumeChart"></canvas>
</div>
</div>
<div class="bg-white rounded-xl shadow-md p-6">
<h3 class="text-lg font-medium text-gray-800 mb-4">Success Rate by Agent</h3>
<div class="h-64">
<canvas id="successRateChart"></canvas>
</div>
</div>
</div>
<!-- Recent Calls Table -->
<div class="bg-white rounded-xl shadow-md overflow-hidden mt-6">
<div class="p-6">
<h3 class="text-lg font-medium text-gray-800 mb-4">Recent Calls</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Agent</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Number</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Duration</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center">
<i class="fas fa-headset text-blue-500"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Support Bot</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">+1 (555) 123-4567</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">2:18</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Successful</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">10 min ago</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a>
<a href="#" class="text-blue-600 hover:text-blue-900">Play</a>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 rounded-full bg-purple-100 flex items-center justify-center">
<i class="fas fa-briefcase text-purple-500"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Sales Assistant</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">+1 (555) 987-6543</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">4:32</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">Successful</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">25 min ago</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a>
<a href="#" class="text-blue-600 hover:text-blue-900">Play</a>
</td>
</tr>
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center">
<i class="fas fa-headset text-blue-500"></i>
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Support Bot</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">+1 (555) 456-7890</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">1:05</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Failed</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">1 hour ago</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<a href="#" class="text-blue-600 hover:text-blue-900 mr-3">Details</a>
<a href="#" class="text-blue-600 hover:text-blue-900">Play</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="bg-white bg-opacity-90 py-8">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<div class="flex items-center space-x-2">
<i class="fas fa-robot text-2xl text-blue-500"></i>
<span class="text-xl font-bold text-gray-800">CallGenie</span>
</div>
<p class="text-gray-500 text-sm mt-1">AI-powered calling agents for your business</p>
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-500 hover:text-blue-500">Terms</a>
<a href="#" class="text-gray-500 hover:text-blue-500">Privacy</a>
<a href="#" class="text-gray-500 hover:text-blue-500">Contact</a>
</div>
</div>
<div class="mt-8 pt-8 border-t border-gray-200 text-center text-gray-500 text-sm">
© 2025 OrionixLabs. All rights reserved.
</div>
</div>
</footer>
<!-- Login Modal -->
<div id="loginModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl shadow-xl w-full max-w-md">
<div class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-2xl font-bold text-gray-800">Welcome to CallGenie</h3>
<button id="closeLoginModalBtn" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-4">
<div>
<label for="loginEmail" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input type="email" id="loginEmail" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="your@email.com">
</div>
<div>
<label for="loginPassword" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<input type="password" id="loginPassword" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="••••••••">
</div>
<div class="flex items-center justify-between">
<label class="inline-flex items-center">
<input type="checkbox" class="rounded text-blue-500">
<span class="ml-2 text-sm text-gray-600">Remember me</span>
</label>
<a href="#" class="text-sm text-blue-500 hover:text-blue-700">Forgot password?</a>
</div>
<button id="loginSubmitBtn" class="w-full py-2 px-4 bg-blue-500 text-white rounded-md hover:bg-blue-600">
Sign In
</button>
<div class="text-center text-sm text-gray-500">
Don't have an account? <a href="#" class="text-blue-500 hover:text-blue-700">Sign up</a>
</div>
<div class="relative mt-6">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white text-gray-500">Or continue with</span>
</div>
</div>
<div class="grid grid-cols-3 gap-3 mt-4">
<button class="flex items-center justify-center py-2 px-4 border border-gray-300 rounded-md bg-white text-gray-700 hover:bg-gray-50">
<i class="fab fa-google text-red-500 mr-2"></i>
<span class="text-sm">Google</span>
</button>
<button class="flex items-center justify-center py-2 px-4 border border-gray-300 rounded-md bg-white text-gray-700 hover:bg-gray-50">
<i class="fab fa-microsoft text-blue-500 mr-2"></i>
<span class="text-sm">Microsoft</span>
</button>
<button class="flex items-center justify-center py-2 px-4 border border-gray-300 rounded-md bg-white text-gray-700 hover:bg-gray-50">
<i class="fab fa-apple text-gray-800 mr-2"></i>
<span class="text-sm">Apple</span>
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Background Animation
VANTA.NET({
el: "#vanta-bg",
mouseControls: true,
touchControls: true,
gyroControls: false,
minHeight: 200.00,
minWidth: 200.00,
scale: 1.00,
scaleMobile: 1.00,
color: 0x3b82f6,
backgroundColor: 0xf8fafc,
points: 12.00,
maxDistance: 22.00,
spacing: 18.00
});
// Mobile Menu Toggle
document.getElementById('mobileMenuBtn').addEventListener('click', function() {
const menu = document.getElementById('mobileMenu');
menu.classList.toggle('hidden');
});
// Login Modal
const loginModal = document.getElementById('loginModal');
document.getElementById('loginBtn').addEventListener('click', function() {
loginModal.classList.remove('hidden');
});
document.getElementById('closeLoginModalBtn').addEventListener('click', function() {
loginModal.classList.add('hidden');
});
// Create Agent Wizard
const createAgentSection = document.getElementById('createAgentSection');
document.getElementById('createNewAgentBtn').addEventListener('click', function() {
createAgentSection.classList.remove('hidden');
window.scrollTo({
top: createAgentSection.offsetTop - 20,
behavior: 'smooth'
});
});
document.getElementById('closeCreateAgentBtn').addEventListener('click', function() {
createAgentSection.classList.add('hidden');
});
// Call Simulation
const callSimulation = document.getElementById('callSimulation');
function openCallSimulation(agentName, agentRole) {
document.getElementById('simAgentName').textContent = agentName;
document.getElementById('simAgentRole').textContent = agentRole;
callSimulation.classList.remove('hidden');
window.scrollTo({
top: callSimulation.offsetTop - 20,
behavior: 'smooth'
});
}
document.getElementById('closeCallSimulationBtn').addEventListener('click', function() {
callSimulation.classList.add('hidden');
});
// Wizard Tabs
const tabs = document.querySelectorAll('.wizard-tab');
const tabContents = document.querySelectorAll('.tab-content');
const prevTabBtn = document.getElementById('prevTabBtn');
const nextTabBtn = document.getElementById('nextTabBtn');
const finishBtn = document.getElementById('finishBtn');
let currentTab = 0;
function showTab(index) {
// Hide all tab contents
tabContents.forEach(content => {
content.classList.remove('active');
});
// Show the selected tab content
tabContents[index].classList.add('active');
// Update tab styling
tabs.forEach((tab, i) => {
if (i === index) {
tab.classList.add('text-blue-500', 'border-blue-500');
tab.classList.remove('text-gray-500');
} else {
tab.classList.remove('text-blue-500', 'border-blue-500');
tab.classList.add('text-gray-500');
}
});
// Update navigation buttons
if (index === 0) {
prevTabBtn.disabled = true;
nextTabBtn.classList.remove('hidden');
finishBtn.classList.add('hidden');
} else if (index === tabs.length - 1) {
prevTabBtn.disabled = false;
nextTabBtn.classList.add('hidden');
finishBtn.classList.remove('hidden');
} else {
prevTabBtn.disabled = false;
nextTabBtn.classList.remove('hidden');
finishBtn.classList.add('hidden');
}
currentTab = index;
}
// Initialize first tab
showTab(0);
// Tab click event
tabs.forEach((tab, index) => {
tab.addEventListener('click', () => {
showTab(index);
});
});
// Navigation buttons
nextTabBtn.addEventListener('click', () => {
showTab(currentTab + 1);
});
prevTabBtn.addEventListener('click', () => {
showTab(currentTab - 1);
});
finishBtn.addEventListener('click', () => {
const agentName = document.getElementById('agentName').value || 'New Agent';
const agentRole = document.getElementById('agentRole').value || 'AI Calling Agent';
// Close creation wizard
createAgentSection.classList.add('hidden');
// Open call simulation with new agent
openCallSimulation(agentName, agentRole);
// Show success message
alert(`Agent "${agentName}" created successfully!`);
});
// Script Type Toggle
const scriptTypeRadios = document.querySelectorAll('input[name="scriptType"]');
const guidedScriptSection = document.getElementById('guidedScriptSection');
const freeformScriptSection = document.getElementById('freeformScriptSection');
scriptTypeRadios.forEach(radio => {
radio.addEventListener('change', function() {
if (this.value === 'guided') {
guidedScriptSection.classList.remove('hidden');
freeformScriptSection.classList.add('hidden');
} else {
guidedScriptSection.classList.add('hidden');
freeformScriptSection.classList.remove('hidden');
}
});
});
// Voice Preview
document.getElementById('testVoiceBtn').addEventListener('click', function() {
const voiceType = document.querySelector('input[name="voiceType"]:checked').value;
let previewText = "Hello, this is your CallGenie AI agent. How can I help you today?";
// Use the Web Speech API for voice synthesis (browser support varies)
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(previewText);
// Set voice properties based on selection
switch(voiceType) {
case 'standard-female':
utterance.rate = 1.0;
utterance.pitch = 1.0;
break;
case 'standard-male':
utterance.rate = 1.0;
utterance.pitch = 0.9;
break;
case 'youthful-female':
utterance.rate = 1.2;
utterance.pitch = 1.1;
break;
case 'authoritative-male':
utterance.rate = 0.9;
utterance.pitch = 0.8;
break;
}
// Update the voice preview text
document.getElementById('previewVoiceType').textContent = this.parentElement.querySelector('span').textContent;
// Speak the text
window.speechSynthesis.speak(utterance);
} else {
alert("Your browser doesn't support voice preview. Try Chrome or Edge.");
}
});
// Update agent preview when name/role changes
document.getElementById('agentName').addEventListener('input', function() {
document.getElementById('previewAgentName').textContent = this.value || 'New Agent';
});
document.getElementById('agentRole').addEventListener('input', function() {
document.getElementById('previewAgentRole').textContent = this.value || 'AI Calling Agent';
});
// Call Simulation Functionality
const startCallBtn = document.getElementById('startCallBtn');
const endCallBtn = document.getElementById('endCallBtn');
const callDisplay = document.getElementById('callDisplay');
const callTranscript = document.getElementById('callTranscript');
const callInputArea = document.getElementById('callInputArea');
const callInput = document.getElementById('callInput');
const sendCallBtn = document.getElementById('sendCallBtn');
const voiceInputBtn = document.getElementById('voiceInputBtn');
startCallBtn.addEventListener('click', function() {
// Update UI for active call
this.classList.add('hidden');
endCallBtn.classList.remove('opacity-50', 'cursor-not-allowed');
callDisplay.classList.add('hidden');
callTranscript.classList.remove('hidden');
callInputArea.classList.remove('hidden');
// Add greeting to transcript
addMessageToTranscript('agent', "Hello! This is your CallGenie AI assistant. How can I help you today?");
// Simulate AI response after a delay
setTimeout(() => {
addMessageToTranscript('agent', "I'm here to assist you with any questions you might have. What would you like to know?");
}, 1500);
});
endCallBtn.addEventListener('click', function() {
// Add closing message
addMessageToTranscript('agent', "Thank you for using CallGenie. Have a great day!");
// Reset UI after delay
setTimeout(() => {
this.classList.add('opacity-50', 'cursor-not-allowed');
startCallBtn.classList.remove('hidden');
callDisplay.classList.remove('hidden');
callTranscript.classList.add('hidden');
callInputArea.classList.add('hidden');
// Clear transcript for next call
callTranscript.innerHTML = '';
}, 1000);
});
sendCallBtn.addEventListener('click', sendMessage);
callInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
function sendMessage() {
const message = callInput.value.trim();
if (message) {
// Add user message to transcript
addMessageToTranscript('user', message);
callInput.value = '';
// Simulate AI response after a delay
setTimeout(() => {
const responses = [
"I understand your question. Let me look that up for you.",
"That's a great question! Here's what I found...",
"I can help with that. The information you need is...",
"Thanks for asking. Based on my knowledge...",
"Let me check my resources for the most accurate answer."
];
const randomResponse = responses[Math.floor(Math.random() * responses.length)];
addMessageToTranscript('agent', randomResponse);
// Scroll to bottom of transcript
callTranscript.scrollTop = callTranscript.scrollHeight;
}, 1000 + Math.random() * 2000);
}
}
function addMessageToTranscript(sender, message) {
const messageDiv = document.createElement('div');
messageDiv.classList.add('call-bubble', sender === 'user' ? 'user-bubble' : 'agent-bubble');
messageDiv.textContent = message;
callTranscript.appendChild(messageDiv);
// Scroll to bottom of transcript
callTranscript.scrollTop = callTranscript.scrollHeight;
}
// Voice Input (simulated)
voiceInputBtn.addEventListener('click', function() {
if (!('webkitSpeechRecognition' in window) && !('SpeechRecognition' in window)) {
alert("Your browser doesn't support voice input. Try Chrome or Edge.");
return;
}
this.innerHTML = '<i class="fas fa-microphone-slash mr-1"></i> Stop Listening';
callInput.placeholder = "Listening...";
// Simulate voice recognition
setTimeout(() => {
const sampleQuestions = [
"How does this service work?",
"What are your business hours?",
"Can I speak to a human representative?",
"Where are you located?",
"What payment methods do you accept?"
];
const randomQuestion = sampleQuestions[Math.floor(Math.random() * sampleQuestions.length)];
callInput.value = randomQuestion;
callInput.placeholder = "Type your message...";
this.innerHTML = '<i class="fas fa-microphone mr-1"></i> Use Voice Input';
// Auto-send the message
sendMessage();
}, 2000);
});
// 3D Agent Avatar
function initAgentAvatar() {
const canvas = document.getElementById('agentCanvas');
const width = canvas.offsetWidth;
const height = canvas.offsetHeight;
// Set up Three.js scene
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(width, height);
canvas.appendChild(renderer.domElement);
// Add lights
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// Create a simple head model (sphere for demo)
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshPhongMaterial({
color: 0x3b82f6,
specular: 0x111111,
shininess: 30
});
const head = new THREE.Mesh(geometry, material);
scene.add(head);
// Position camera
camera.position.z = 3;
// Add subtle animation
let time = 0;
function animate() {
requestAnimationFrame(animate);
time += 0.01;
// Slight head movement
head.rotation.y = Math.sin(time * 0.5) * 0.1;
head.rotation.x = Math.sin(time * 0.3) * 0.05;
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', function() {
const newWidth = canvas.offsetWidth;
const newHeight = canvas.offsetHeight;
camera.aspect = newWidth / newHeight;
camera.updateProjectionMatrix();
renderer.setSize(newWidth, newHeight);
});
}
// Initialize agent avatar when create agent section is opened
document.getElementById('createNewAgentBtn').addEventListener('click', initAgentAvatar);
// Charts (using Chart.js)
function initCharts() {
// Call Volume Chart
const callVolumeCtx = document.getElementById('callVolumeChart').getContext('2d');
const callVolumeChart = new Chart(callVolumeCtx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Calls',
data: [45, 78, 56, 89, 76, 55, 40],
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
borderWidth: 2,
fill: true,
tension: 0.4
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true
}
}
}
});
// Success Rate Chart
const successRateCtx = document.getElementById('successRateChart').getContext('2d');
const successRateChart = new Chart(successRateCtx, {
type: 'bar',
data: {
labels: ['Support Bot', 'Sales Asst', 'Tech Help'],
datasets: [{
label: 'Success Rate',
data: [87, 92, 78],
backgroundColor: [
'rgba(59, 130, 246, 0.7)',
'rgba(16, 185, 129, 0.7)',
'rgba(249, 115, 22, 0.7)'
],
borderColor: [
'rgba(59, 130, 246, 1)',
'rgba(16, 185, 129, 1)',
'rgba(249, 115, 22, 1)'
],
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: {
callback: function(value) {
return value + '%';
}
}
}
}
}
});
}
// Initialize charts when page loads
document.addEventListener('DOMContentLoaded', function() {
// Load Chart.js if not already loaded
if (typeof Chart === 'undefined') {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/chart.js';
script.onload = initCharts;
document.head.appendChild(script);
} else {
initCharts();
}
});
</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=ebonivon/call-genie" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>