| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>NexusDial - Advanced Cloud Dialer</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> |
| tailwind.config = { |
| theme: { |
| extend: { |
| colors: { |
| primary: '#4f46e5', |
| secondary: '#10b981', |
| accent: '#f59e0b', |
| dark: '#1e293b', |
| light: '#f8fafc' |
| } |
| } |
| } |
| } |
| </script> |
| <style> |
| @keyframes pulse { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0.5; } |
| } |
| .pulse-animation { |
| animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
| } |
| .agent-card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); |
| } |
| .call-animation { |
| animation: ring 1.5s ease infinite; |
| } |
| @keyframes ring { |
| 0% { transform: rotate(0); } |
| 10% { transform: rotate(-5deg); } |
| 20% { transform: rotate(5deg); } |
| 30% { transform: rotate(-5deg); } |
| 40% { transform: rotate(5deg); } |
| 50% { transform: rotate(0); } |
| 100% { transform: rotate(0); } |
| } |
| .sidebar { |
| scrollbar-width: thin; |
| scrollbar-color: #4f46e5 #e2e8f0; |
| } |
| .sidebar::-webkit-scrollbar { |
| width: 6px; |
| } |
| .sidebar::-webkit-scrollbar-track { |
| background: #e2e8f0; |
| } |
| .sidebar::-webkit-scrollbar-thumb { |
| background-color: #4f46e5; |
| border-radius: 3px; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50 font-sans antialiased"> |
| <div class="flex h-screen overflow-hidden"> |
| |
| <div class="hidden md:flex md:flex-shrink-0"> |
| <div class="flex flex-col w-64 bg-white border-r border-gray-200"> |
| <div class="flex items-center justify-center h-16 px-4 bg-primary text-white"> |
| <div class="flex items-center"> |
| <i class="fas fa-phone-alt mr-2"></i> |
| <span class="text-xl font-semibold">NexusDial</span> |
| </div> |
| </div> |
| <div class="flex flex-col flex-grow overflow-y-auto sidebar"> |
| <nav class="flex-1 px-2 py-4 space-y-1"> |
| <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md bg-indigo-100 text-primary"> |
| <i class="fas fa-tachometer-alt mr-3"></i> |
| Dashboard |
| </a> |
| <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-100 hover:text-gray-900"> |
| <i class="fas fa-users mr-3"></i> |
| Contacts |
| </a> |
| <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-100 hover:text-gray-900"> |
| <i class="fas fa-chart-line mr-3"></i> |
| Analytics |
| </a> |
| <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-100 hover:text-gray-900"> |
| <i class="fas fa-cog mr-3"></i> |
| Settings |
| </a> |
| <a href="#" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-100 hover:text-gray-900"> |
| <i class="fas fa-question-circle mr-3"></i> |
| Help |
| </a> |
| </nav> |
| <div class="px-4 py-4 border-t border-gray-200"> |
| <div class="flex items-center"> |
| <img class="w-10 h-10 rounded-full" src="https://randomuser.me/api/portraits/women/44.jpg" alt="User profile"> |
| <div class="ml-3"> |
| <p class="text-sm font-medium text-gray-700">Sarah Johnson</p> |
| <p class="text-xs font-medium text-gray-500">Admin</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex flex-col flex-1 overflow-hidden"> |
| |
| <div class="flex items-center justify-between h-16 px-4 bg-white border-b border-gray-200"> |
| <div class="flex items-center"> |
| <button class="md:hidden text-gray-500 focus:outline-none"> |
| <i class="fas fa-bars"></i> |
| </button> |
| <h1 class="ml-4 text-lg font-semibold text-gray-800">Dialer Dashboard</h1> |
| </div> |
| <div class="flex items-center space-x-4"> |
| <button class="p-1 text-gray-400 rounded-full hover:text-gray-500 focus:outline-none"> |
| <i class="fas fa-bell"></i> |
| </button> |
| <button class="p-1 text-gray-400 rounded-full hover:text-gray-500 focus:outline-none"> |
| <i class="fas fa-envelope"></i> |
| </button> |
| <div class="relative"> |
| <button class="flex items-center text-sm text-gray-700 focus:outline-none"> |
| <span class="sr-only">Open user menu</span> |
| <img class="w-8 h-8 rounded-full" src="https://randomuser.me/api/portraits/women/44.jpg" alt="User profile"> |
| </button> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="flex-1 overflow-auto p-4"> |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> |
| |
| <div class="lg:col-span-2 space-y-6"> |
| |
| <div class="bg-white rounded-lg shadow p-6"> |
| <div class="flex justify-between items-center mb-4"> |
| <h2 class="text-lg font-semibold text-gray-800">Campaign Performance</h2> |
| <div class="flex space-x-2"> |
| <button class="px-3 py-1 text-xs bg-primary text-white rounded-md">Today</button> |
| <button class="px-3 py-1 text-xs bg-gray-200 text-gray-700 rounded-md">Week</button> |
| <button class="px-3 py-1 text-xs bg-gray-200 text-gray-700 rounded-md">Month</button> |
| </div> |
| </div> |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4"> |
| <div class="bg-indigo-50 p-4 rounded-lg"> |
| <div class="text-sm font-medium text-indigo-600">Total Calls</div> |
| <div class="mt-1 text-2xl font-semibold text-gray-900">1,248</div> |
| <div class="text-xs text-green-600 flex items-center"> |
| <i class="fas fa-arrow-up mr-1"></i> 12% from yesterday |
| </div> |
| </div> |
| <div class="bg-green-50 p-4 rounded-lg"> |
| <div class="text-sm font-medium text-green-600">Connected</div> |
| <div class="mt-1 text-2xl font-semibold text-gray-900">842</div> |
| <div class="text-xs text-green-600 flex items-center"> |
| <i class="fas fa-arrow-up mr-1"></i> 8% from yesterday |
| </div> |
| </div> |
| <div class="bg-yellow-50 p-4 rounded-lg"> |
| <div class="text-sm font-medium text-yellow-600">Conversion</div> |
| <div class="mt-1 text-2xl font-semibold text-gray-900">312</div> |
| <div class="text-xs text-red-600 flex items-center"> |
| <i class="fas fa-arrow-down mr-1"></i> 3% from yesterday |
| </div> |
| </div> |
| <div class="bg-red-50 p-4 rounded-lg"> |
| <div class="text-sm font-medium text-red-600">DNC Hits</div> |
| <div class="mt-1 text-2xl font-semibold text-gray-900">24</div> |
| <div class="text-xs text-green-600 flex items-center"> |
| <i class="fas fa-arrow-down mr-1"></i> 5% from yesterday |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-lg shadow p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Dialer Controls</h2> |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Load Contacts</label> |
| <div class="flex space-x-2 mb-4"> |
| <label class="flex-1"> |
| <div class="flex items-center justify-center px-4 py-2 bg-white border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 cursor-pointer"> |
| <i class="fas fa-file-upload mr-2"></i> Upload CSV |
| <input type="file" class="hidden" id="csv-upload" accept=".csv,.txt"> |
| </div> |
| </label> |
| <button class="px-4 py-2 bg-primary text-white rounded-md shadow-sm text-sm font-medium hover:bg-indigo-700 focus:outline-none"> |
| <i class="fas fa-database mr-2"></i> From CRM |
| </button> |
| </div> |
| |
| <label class="block text-sm font-medium text-gray-700 mb-1">Or paste numbers</label> |
| <textarea id="paste-list" rows="4" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary" placeholder="Enter phone numbers, one per line..."></textarea> |
| |
| <div class="flex justify-between mt-2"> |
| <span id="queue-count" class="text-sm text-gray-500">0 numbers in queue</span> |
| <button id="clear-queue" class="text-sm text-red-500 hover:text-red-700"> |
| <i class="fas fa-trash-alt mr-1"></i> Clear |
| </button> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Dialer Settings</label> |
| <div class="space-y-3"> |
| <div> |
| <label class="block text-xs text-gray-500 mb-1">Dial Mode</label> |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| <option>Predictive (Auto)</option> |
| <option>Progressive</option> |
| <option>Preview</option> |
| <option>Manual</option> |
| </select> |
| </div> |
| |
| <div class="grid grid-cols-2 gap-3"> |
| <div> |
| <label class="block text-xs text-gray-500 mb-1">Max Calls/Hour</label> |
| <input type="number" value="60" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| </div> |
| <div> |
| <label class="block text-xs text-gray-500 mb-1">Call Timeout</label> |
| <input type="number" value="30" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| </div> |
| </div> |
| |
| <div class="flex items-center"> |
| <input id="enable-recording" type="checkbox" checked class="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded"> |
| <label for="enable-recording" class="ml-2 block text-sm text-gray-700">Record calls</label> |
| </div> |
| |
| <div class="flex space-x-2 pt-2"> |
| <button id="start-dialer" class="flex-1 px-4 py-2 bg-green-600 text-white rounded-md shadow-sm text-sm font-medium hover:bg-green-700 focus:outline-none"> |
| <i class="fas fa-play mr-2"></i> Start Dialing |
| </button> |
| <button id="pause-dialer" class="flex-1 px-4 py-2 bg-yellow-500 text-white rounded-md shadow-sm text-sm font-medium hover:bg-yellow-600 focus:outline-none"> |
| <i class="fas fa-pause mr-2"></i> Pause |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-lg shadow overflow-hidden"> |
| <div class="px-6 py-4 border-b border-gray-200"> |
| <h2 class="text-lg font-semibold text-gray-800">Active Calls</h2> |
| </div> |
| <div class="divide-y divide-gray-200"> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <div class="h-10 w-10 rounded-full bg-green-100 flex items-center justify-center text-green-600"> |
| <i class="fas fa-phone-alt call-animation"></i> |
| </div> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">+1 (555) 123-4567</p> |
| <p class="text-xs text-gray-500">02:34</p> |
| </div> |
| <div class="flex items-center justify-between mt-1"> |
| <p class="text-xs text-gray-500">Agent: Michael Scott</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800">Connected</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <div class="h-10 w-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-600"> |
| <i class="fas fa-phone-alt call-animation"></i> |
| </div> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">+1 (555) 987-6543</p> |
| <p class="text-xs text-gray-500">01:12</p> |
| </div> |
| <div class="flex items-center justify-between mt-1"> |
| <p class="text-xs text-gray-500">Agent: Dwight Schrute</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800">Ringing</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <div class="h-10 w-10 rounded-full bg-yellow-100 flex items-center justify-center text-yellow-600"> |
| <i class="fas fa-phone-alt"></i> |
| </div> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">+1 (555) 456-7890</p> |
| <p class="text-xs text-gray-500">00:45</p> |
| </div> |
| <div class="flex items-center justify-between mt-1"> |
| <p class="text-xs text-gray-500">Agent: Jim Halpert</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-yellow-100 text-yellow-800">On Hold</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="space-y-6"> |
| |
| <div class="bg-white rounded-lg shadow overflow-hidden"> |
| <div class="px-6 py-4 border-b border-gray-200"> |
| <div class="flex items-center justify-between"> |
| <h2 class="text-lg font-semibold text-gray-800">Agent Status</h2> |
| <span class="text-xs bg-primary text-white px-2 py-1 rounded-full">10 Agents</span> |
| </div> |
| </div> |
| <div class="divide-y divide-gray-200"> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <img class="h-10 w-10 rounded-full" src="https://randomuser.me/api/portraits/men/32.jpg" alt="Agent"> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">Michael Scott</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-green-100 text-green-800">On Call</span> |
| </div> |
| <div class="mt-1"> |
| <p class="text-xs text-gray-500">+1 (555) 123-4567 (02:34)</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <img class="h-10 w-10 rounded-full" src="https://randomuser.me/api/portraits/men/44.jpg" alt="Agent"> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">Dwight Schrute</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-blue-100 text-blue-800">Ringing</span> |
| </div> |
| <div class="mt-1"> |
| <p class="text-xs text-gray-500">+1 (555) 987-6543 (01:12)</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <img class="h-10 w-10 rounded-full" src="https://randomuser.me/api/portraits/men/22.jpg" alt="Agent"> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">Jim Halpert</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-yellow-100 text-yellow-800">On Hold</span> |
| </div> |
| <div class="mt-1"> |
| <p class="text-xs text-gray-500">+1 (555) 456-7890 (00:45)</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="p-4 hover:bg-gray-50"> |
| <div class="flex items-center"> |
| <div class="flex-shrink-0"> |
| <img class="h-10 w-10 rounded-full" src="https://randomuser.me/api/portraits/women/63.jpg" alt="Agent"> |
| </div> |
| <div class="ml-4 flex-1"> |
| <div class="flex items-center justify-between"> |
| <p class="text-sm font-medium text-gray-900">Pam Beesly</p> |
| <span class="px-2 py-1 text-xs rounded-full bg-gray-100 text-gray-800">Available</span> |
| </div> |
| <div class="mt-1"> |
| <p class="text-xs text-gray-500">Ready for next call</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="px-6 py-3 bg-gray-50 text-center"> |
| <button class="text-sm text-primary hover:text-indigo-700 font-medium"> |
| <i class="fas fa-plus mr-1"></i> Add Agent |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-lg shadow p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Call Disposition</h2> |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Status</label> |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| <option>Interested - Follow up needed</option> |
| <option>Not Interested</option> |
| <option>Call Back Later</option> |
| <option>Do Not Call</option> |
| <option>Wrong Number</option> |
| <option>No Answer</option> |
| <option>Busy</option> |
| </select> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Notes</label> |
| <textarea rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm" placeholder="Add call notes..."></textarea> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Next Action</label> |
| <select class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| <option>None</option> |
| <option>Schedule Call Back</option> |
| <option>Send Email</option> |
| <option>Send SMS</option> |
| <option>Create Task</option> |
| </select> |
| </div> |
| |
| <div id="callback-container" class="hidden"> |
| <label class="block text-sm font-medium text-gray-700 mb-1">Callback Date/Time</label> |
| <input type="datetime-local" class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary focus:border-primary text-sm"> |
| </div> |
| |
| <button class="w-full px-4 py-2 bg-primary text-white rounded-md shadow-sm text-sm font-medium hover:bg-indigo-700 focus:outline-none"> |
| <i class="fas fa-save mr-2"></i> Save Disposition |
| </button> |
| </div> |
| </div> |
|
|
| |
| <div class="bg-white rounded-lg shadow p-6"> |
| <h2 class="text-lg font-semibold text-gray-800 mb-4">Quick Stats</h2> |
| <div class="space-y-3"> |
| <div class="flex justify-between"> |
| <span class="text-sm text-gray-600">Calls Today</span> |
| <span class="text-sm font-medium">124</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-sm text-gray-600">Connect Rate</span> |
| <span class="text-sm font-medium">67%</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-sm text-gray-600">Avg Talk Time</span> |
| <span class="text-sm font-medium">2:34</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-sm text-gray-600">Conversion Rate</span> |
| <span class="text-sm font-medium">25%</span> |
| </div> |
| <div class="flex justify-between"> |
| <span class="text-sm text-gray-600">DNC Hits</span> |
| <span class="text-sm font-medium">3</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div id="call-modal" class="fixed inset-0 z-50 hidden overflow-y-auto"> |
| <div class="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> |
| <div class="fixed inset-0 transition-opacity" aria-hidden="true"> |
| <div class="absolute inset-0 bg-gray-500 opacity-75"></div> |
| </div> |
| <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span> |
| <div class="inline-block align-bottom bg-white rounded-lg px-4 pt-5 pb-4 text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6"> |
| <div> |
| <div class="mx-auto flex items-center justify-center h-12 w-12 rounded-full bg-green-100"> |
| <i class="fas fa-phone-alt text-green-600 call-animation"></i> |
| </div> |
| <div class="mt-3 text-center sm:mt-5"> |
| <h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">Incoming Call</h3> |
| <div class="mt-2"> |
| <p class="text-sm text-gray-500" id="caller-number">+1 (555) 123-4567</p> |
| <p class="text-xs text-gray-400 mt-1">John Smith • Acme Corp</p> |
| </div> |
| </div> |
| </div> |
| <div class="mt-5 sm:mt-6 grid grid-cols-2 gap-3"> |
| <button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-600 text-base font-medium text-white hover:bg-green-700 focus:outline-none sm:text-sm"> |
| <i class="fas fa-phone mr-2"></i> Answer |
| </button> |
| <button type="button" class="inline-flex justify-center w-full rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none sm:text-sm"> |
| <i class="fas fa-phone-slash mr-2"></i> Decline |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| let callQueue = []; |
| let isPaused = false; |
| let agents = [ |
| { id: 1, name: "Michael Scott", status: "on-call", avatar: "https://randomuser.me/api/portraits/men/32.jpg", currentCall: "+1 (555) 123-4567", callDuration: "02:34" }, |
| { id: 2, name: "Dwight Schrute", status: "ringing", avatar: "https://randomuser.me/api/portraits/men/44.jpg", currentCall: "+1 (555) 987-6543", callDuration: "01:12" }, |
| { id: 3, name: "Jim Halpert", status: "on-hold", avatar: "https://randomuser.me/api/portraits/men/22.jpg", currentCall: "+1 (555) 456-7890", callDuration: "00:45" }, |
| { id: 4, name: "Pam Beesly", status: "available", avatar: "https://randomuser.me/api/portraits/women/63.jpg", currentCall: null, callDuration: null }, |
| { id: 5, name: "Stanley Hudson", status: "available", avatar: "https://randomuser.me/api/portraits/men/12.jpg", currentCall: null, callDuration: null }, |
| { id: 6, name: "Phyllis Vance", status: "available", avatar: "https://randomuser.me/api/portraits/women/45.jpg", currentCall: null, callDuration: null }, |
| { id: 7, name: "Kevin Malone", status: "break", avatar: "https://randomuser.me/api/portraits/men/65.jpg", currentCall: null, callDuration: null }, |
| { id: 8, name: "Angela Martin", status: "break", avatar: "https://randomuser.me/api/portraits/women/33.jpg", currentCall: null, callDuration: null }, |
| { id: 9, name: "Oscar Martinez", status: "training", avatar: "https://randomuser.me/api/portraits/men/76.jpg", currentCall: null, callDuration: null }, |
| { id: 10, name: "Kelly Kapoor", status: "wrap-up", avatar: "https://randomuser.me/api/portraits/women/22.jpg", currentCall: null, callDuration: null } |
| ]; |
| |
| |
| const csvUpload = document.getElementById('csv-upload'); |
| const pasteList = document.getElementById('paste-list'); |
| const queueCount = document.getElementById('queue-count'); |
| const clearQueueBtn = document.getElementById('clear-queue'); |
| const startDialerBtn = document.getElementById('start-dialer'); |
| const pauseDialerBtn = document.getElementById('pause-dialer'); |
| const callModal = document.getElementById('call-modal'); |
| |
| |
| csvUpload.addEventListener('change', handleCSVUpload); |
| pasteList.addEventListener('input', autoLoadPasteList); |
| clearQueueBtn.addEventListener('click', clearQueue); |
| startDialerBtn.addEventListener('click', startAutoDialing); |
| pauseDialerBtn.addEventListener('click', togglePauseDialer); |
| |
| |
| function updateQueueCount() { |
| const count = callQueue.length; |
| queueCount.textContent = `${count} number${count !== 1 ? 's' : ''} in queue`; |
| } |
| |
| function handleCSVUpload(event) { |
| const file = event.target.files[0]; |
| if (!file) return; |
| |
| const reader = new FileReader(); |
| reader.onload = function(e) { |
| const content = e.target.result; |
| callQueue = content.split('\n') |
| .map(line => line.trim()) |
| .filter(line => line !== ''); |
| |
| updateQueueCount(); |
| showNotification(`Successfully loaded ${callQueue.length} numbers from CSV`); |
| }; |
| reader.readAsText(file); |
| } |
| |
| function autoLoadPasteList() { |
| const inputText = pasteList.value; |
| callQueue = inputText.split('\n') |
| .map(line => line.trim()) |
| .filter(line => line !== ''); |
| |
| updateQueueCount(); |
| } |
| |
| function clearQueue() { |
| callQueue = []; |
| pasteList.value = ''; |
| updateQueueCount(); |
| showNotification('Call queue has been cleared', 'info'); |
| } |
| |
| function startAutoDialing() { |
| if (callQueue.length === 0) { |
| showNotification('Please add numbers to the queue first', 'warning'); |
| return; |
| } |
| |
| showNotification('Dialer started successfully', 'success'); |
| isPaused = false; |
| startDialerBtn.disabled = true; |
| pauseDialerBtn.disabled = false; |
| |
| |
| simulateCalls(); |
| } |
| |
| function togglePauseDialer() { |
| isPaused = !isPaused; |
| if (isPaused) { |
| pauseDialerBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Resume'; |
| showNotification('Dialer paused', 'info'); |
| } else { |
| pauseDialerBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause'; |
| showNotification('Dialer resumed', 'success'); |
| simulateCalls(); |
| } |
| } |
| |
| function simulateCalls() { |
| if (isPaused || callQueue.length === 0) return; |
| |
| |
| const availableAgents = agents.filter(agent => agent.status === 'available'); |
| if (availableAgents.length === 0) { |
| setTimeout(simulateCalls, 2000); |
| return; |
| } |
| |
| |
| availableAgents.slice(0, Math.min(availableAgents.length, callQueue.length)).forEach(agent => { |
| if (callQueue.length === 0) return; |
| |
| const number = callQueue.shift(); |
| updateQueueCount(); |
| |
| |
| agent.status = 'ringing'; |
| agent.currentCall = number; |
| agent.callDuration = '00:00'; |
| |
| |
| showCallModal(number); |
| |
| |
| setTimeout(() => { |
| agent.status = 'on-call'; |
| updateAgentUI(agent); |
| |
| |
| const callDuration = Math.floor(Math.random() * 120) + 30; |
| setTimeout(() => { |
| agent.status = 'wrap-up'; |
| agent.callDuration = null; |
| updateAgentUI(agent); |
| |
| |
| setTimeout(() => { |
| agent.status = 'available'; |
| agent.currentCall = null; |
| updateAgentUI(agent); |
| simulateCalls(); |
| }, 5000); |
| }, callDuration * 1000); |
| }, 3000); |
| }); |
| |
| |
| setTimeout(simulateCalls, 2000); |
| } |
| |
| function updateAgentUI(agent) { |
| |
| console.log(`Agent ${agent.name} status updated to ${agent.status}`); |
| } |
| |
| function showCallModal(number) { |
| document.getElementById('caller-number').textContent = number; |
| callModal.classList.remove('hidden'); |
| |
| |
| setTimeout(() => { |
| if (!callModal.classList.contains('hidden')) { |
| callModal.classList.add('hidden'); |
| } |
| }, 10000); |
| } |
| |
| function showNotification(message, type = 'success') { |
| |
| console.log(`Notification (${type}): ${message}`); |
| } |
| |
| |
| updateQueueCount(); |
| |
| |
| window.addEventListener('click', (event) => { |
| if (event.target === callModal) { |
| callModal.classList.add('hidden'); |
| } |
| }); |
| |
| |
| document.querySelector('select').addEventListener('change', function() { |
| const callbackContainer = document.getElementById('callback-container'); |
| if (this.value === 'Schedule Call Back') { |
| callbackContainer.classList.remove('hidden'); |
| } else { |
| callbackContainer.classList.add('hidden'); |
| } |
| }); |
| </script> |
| </body> |
| </html> |