Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>AI Spam Detector</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="style.css"> | |
| </head> | |
| <body> | |
| <div class="background-glob"></div> | |
| <div class="container"> | |
| <header> | |
| <h1>Spam Shield AI</h1> | |
| <p>Advanced Email Classification System</p> | |
| </header> | |
| <main> | |
| <div class="card glass"> | |
| <div class="input-group"> | |
| <label for="emailContent">Paste your email content here</label> | |
| <textarea id="emailContent" | |
| placeholder="e.g., Congratulations! You've won a $1000 gift card..."></textarea> | |
| </div> | |
| <div class="actions"> | |
| <button id="checkBtn" class="btn-primary"> | |
| <span class="btn-text">Analyze Message</span> | |
| <div class="loader" id="loader"></div> | |
| </button> | |
| </div> | |
| <div id="resultArea" class="result-area hidden"> | |
| <div id="resultCard" class="result-card"> | |
| <span id="resultIcon" class="icon"></span> | |
| <h2 id="resultTitle"></h2> | |
| <p id="resultConfidence"></p> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <footer> | |
| <p>Powered by Python & N8N Integration</p> | |
| </footer> | |
| </div> | |
| <script> | |
| // Use relative path so it works on localhost AND Hugging Face automatically | |
| const API_URL = "/predict"; | |
| const checkBtn = document.getElementById('checkBtn'); | |
| const emailContent = document.getElementById('emailContent'); | |
| const loader = document.getElementById('loader'); | |
| const btnText = document.querySelector('.btn-text'); | |
| const resultArea = document.getElementById('resultArea'); | |
| const resultCard = document.getElementById('resultCard'); | |
| const resultTitle = document.getElementById('resultTitle'); | |
| const resultIcon = document.getElementById('resultIcon'); | |
| const resultConfidence = document.getElementById('resultConfidence'); | |
| checkBtn.addEventListener('click', async () => { | |
| const text = emailContent.value.trim(); | |
| if (!text) { | |
| alert("Please enter some text to analyze."); | |
| return; | |
| } | |
| // UI Loading State | |
| checkBtn.disabled = true; | |
| loader.style.display = 'block'; | |
| btnText.style.opacity = '0'; | |
| resultArea.classList.add('hidden'); | |
| try { | |
| const response = await fetch(API_URL, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify({ message: text }) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`Server error: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| displayResult(data); | |
| } catch (error) { | |
| console.error("Error:", error); | |
| alert("An error occurred. If running locally, make sure app.py is running. If on HF, checks logs."); | |
| } finally { | |
| checkBtn.disabled = false; | |
| loader.style.display = 'none'; | |
| btnText.style.opacity = '1'; | |
| } | |
| }); | |
| function displayResult(data) { | |
| let prediction = data.prediction || "Unknown"; | |
| let confidence = data.confidence || 0; | |
| resultArea.classList.remove('hidden'); | |
| resultCard.className = 'result-card'; // reset | |
| if (prediction.toLowerCase() === 'spam') { | |
| resultCard.classList.add('spam'); | |
| resultTitle.innerText = "Spam Detected"; | |
| resultIcon.innerText = "⚠️"; | |
| resultConfidence.innerText = `Confidence: ${(confidence * 100).toFixed(1)}%`; | |
| } else { | |
| resultCard.classList.add('ham'); | |
| resultTitle.innerText = "Safe Message"; | |
| resultIcon.innerText = "✅"; | |
| resultConfidence.innerText = `Confidence: ${(confidence * 100).toFixed(1)}%`; | |
| } | |
| } | |
| </script> | |
| </body> | |
| </html> |