Design me a modern SaaS web app for Prospect AI that integrates with the following FastAPI backend endpoints:
980f6a1 verified | <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Training - Prospect AI</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script> | |
| tailwind.config = { | |
| darkMode: 'class', | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: '#00f2fe', | |
| secondary: '#4facfe', | |
| dark: '#0f172a', | |
| darker: '#0a0f1f' | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: #0f172a; | |
| color: #f1f5f9; | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #0f172a 0%, #0a0f1f 100%); | |
| } | |
| .fade-in { | |
| animation: fadeIn 0.5s ease-in; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| </style> | |
| </head> | |
| <body class="gradient-bg"> | |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> | |
| <!-- Header --> | |
| <header class="flex justify-between items-center mb-10 py-6"> | |
| <div class="flex items-center space-x-3"> | |
| <div class="w-10 h-10 rounded-full bg-gradient-to-r from-primary to-secondary flex items-center justify-center"> | |
| <i data-feather="cpu" class="text-dark"></i> | |
| </div> | |
| <h1 class="text-2xl font-bold">Prospect AI</h1> | |
| </div> | |
| <nav class="flex space-x-6"> | |
| <a href="landing.html" class="text-gray-400 hover:text-primary transition">Home</a> | |
| <a href="training.html" class="text-primary font-medium">Training</a> | |
| <a href="ml-prospecting.html" class="text-gray-400 hover:text-primary transition">ML Prospecting</a> | |
| <a href="crewai-enrichment.html" class="text-gray-400 hover:text-primary transition">CrewAI Enrichment</a> | |
| <a href="hybrid-prospecting.html" class="text-gray-400 hover:text-primary transition">Hybrid Prospecting</a> | |
| </nav> | |
| </header> | |
| <!-- Training Section --> | |
| <section class="bg-darker rounded-2xl shadow-xl p-8 fade-in"> | |
| <div class="text-center mb-8"> | |
| <h2 class="text-3xl font-bold mb-2">Train Your Model</h2> | |
| <p class="text-gray-400">Upload your lead data to train the Prospect AI model</p> | |
| </div> | |
| <div class="border-2 border-dashed border-gray-700 rounded-xl p-10 text-center"> | |
| <div class="flex flex-col items-center justify-center"> | |
| <i data-feather="upload" class="w-12 h-12 text-gray-500 mb-4"></i> | |
| <h3 class="text-lg font-semibold text-gray-300 mb-2">Upload Training Data</h3> | |
| <p class="text-gray-500 mb-6">Upload a CSV file with your historical lead data</p> | |
| <div class="flex flex-col sm:flex-row gap-4 w-full max-w-md"> | |
| <input | |
| type="file" | |
| id="trainingFile" | |
| accept=".csv" | |
| class="hidden" | |
| > | |
| <button | |
| id="uploadButton" | |
| class="bg-gradient-to-r from-primary to-secondary hover:opacity-90 text-dark px-6 py-3 rounded-lg font-medium transition duration-200 flex items-center justify-center w-full" | |
| > | |
| <i data-feather="file-text" class="w-5 h-5 mr-2"></i> | |
| Select CSV File | |
| </button> | |
| </div> | |
| <div id="fileName" class="mt-4 text-gray-400 text-sm hidden"> | |
| <span id="fileText"></span> | |
| </div> | |
| <button | |
| id="trainButton" | |
| class="mt-6 bg-primary hover:opacity-90 text-dark px-8 py-3 rounded-lg font-bold transition duration-200 hidden" | |
| > | |
| Train Model | |
| </button> | |
| </div> | |
| </div> | |
| <div id="resultMessage" class="mt-8 text-center hidden"> | |
| <div class="inline-flex items-center px-4 py-2 rounded-full bg-green-900/30 text-green-400"> | |
| <i data-feather="check-circle" class="w-5 h-5 mr-2"></i> | |
| <span id="resultText">Model trained successfully!</span> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- Footer --> | |
| <footer class="mt-12 text-center text-gray-500 text-sm"> | |
| <p>© 2025 Prospect AI • Smarter Lead Generation</p> | |
| </footer> | |
| </div> | |
| <script> | |
| feather.replace(); | |
| document.addEventListener('DOMContentLoaded', function() { | |
| const uploadButton = document.getElementById('uploadButton'); | |
| const trainingFile = document.getElementById('trainingFile'); | |
| const fileName = document.getElementById('fileName'); | |
| const fileText = document.getElementById('fileText'); | |
| const trainButton = document.getElementById('trainButton'); | |
| const resultMessage = document.getElementById('resultMessage'); | |
| const resultText = document.getElementById('resultText'); | |
| uploadButton.addEventListener('click', () => { | |
| trainingFile.click(); | |
| }); | |
| trainingFile.addEventListener('change', (e) => { | |
| if (e.target.files.length > 0) { | |
| fileText.textContent = e.target.files[0].name; | |
| fileName.classList.remove('hidden'); | |
| trainButton.classList.remove('hidden'); | |
| } | |
| }); | |
| trainButton.addEventListener('click', async () => { | |
| if (!trainingFile.files[0]) return; | |
| const formData = new FormData(); | |
| formData.append('file', trainingFile.files[0]); | |
| trainButton.innerHTML = '<i data-feather="loader" class="w-5 h-5 mr-2 animate-spin"></i>Training...'; | |
| feather.replace(); | |
| trainButton.disabled = true; | |
| try { | |
| const response = await fetch('http://localhost:8000/train', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (response.ok) { | |
| resultText.textContent = 'Model trained successfully!'; | |
| resultMessage.classList.remove('hidden'); | |
| } else { | |
| resultText.textContent = 'Training failed. Please try again.'; | |
| resultMessage.classList.remove('hidden'); | |
| resultMessage.querySelector('div').className = 'inline-flex items-center px-4 py-2 rounded-full bg-red-900/30 text-red-400'; | |
| } | |
| } catch (error) { | |
| resultText.textContent = 'Error connecting to server.'; | |
| resultMessage.classList.remove('hidden'); | |
| resultMessage.querySelector('div').className = 'inline-flex items-center px-4 py-2 rounded-full bg-red-900/30 text-red-400'; | |
| } finally { | |
| trainButton.innerHTML = 'Train Model'; | |
| feather.replace(); | |
| trainButton.disabled = false; | |
| } | |
| }); | |
| }); | |
| </script> | |
| </body> | |
| </html> |