Spaces:
Running
Running
| <html lang="de"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>AI Dokumenten Hub</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=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Phosphor Icons für moderne Icons --> | |
| <script src="https://unpkg.com/@phosphor-icons/web"></script> | |
| <style> | |
| :root { | |
| /* Farbpalette - Modern & Professional */ | |
| --primary: #6366f1; | |
| --primary-dark: #4f46e5; | |
| --secondary: #ec4899; | |
| --bg-dark: #0f172a; | |
| --bg-card: #1e293b; | |
| --bg-hover: #334155; | |
| --text-main: #f8fafc; | |
| --text-muted: #94a3b8; | |
| --border: #334155; | |
| --success: #10b981; | |
| --glass: rgba(30, 41, 59, 0.7); | |
| /* Layout */ | |
| --nav-height: 70px; | |
| --header-height: 60px; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| -webkit-tap-highlight-color: transparent; | |
| } | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: var(--bg-dark); | |
| color: var(--text-main); | |
| height: 100vh; | |
| overflow: hidden; /* App-like feel */ | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* --- Header --- */ | |
| header { | |
| height: var(--header-height); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 20px; | |
| background: rgba(15, 23, 42, 0.95); | |
| border-bottom: 1px solid var(--border); | |
| z-index: 100; | |
| } | |
| .brand { | |
| font-weight: 700; | |
| font-size: 1.2rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .brand i { | |
| color: var(--primary); | |
| font-size: 1.5rem; | |
| } | |
| .built-with { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| opacity: 0.7; | |
| transition: opacity 0.2s; | |
| } | |
| .built-with:hover { | |
| opacity: 1; | |
| color: var(--primary); | |
| } | |
| /* --- Main Layout --- */ | |
| main { | |
| flex: 1; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .view-container { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| overflow-y: auto; | |
| padding: 20px; | |
| padding-bottom: 100px; /* Space for FAB and Nav */ | |
| opacity: 0; | |
| pointer-events: none; | |
| transform: translateY(20px); | |
| transition: opacity 0.3s ease, transform 0.3s ease; | |
| display: none; /* Helper to ensure visibility */ | |
| } | |
| .view-container.active { | |
| opacity: 1; | |
| pointer-events: all; | |
| transform: translateY(0); | |
| display: block; | |
| } | |
| h2 { | |
| font-size: 1.5rem; | |
| margin-bottom: 20px; | |
| font-weight: 600; | |
| } | |
| /* --- Upload Area (Drag & Drop) --- */ | |
| .upload-zone { | |
| border: 2px dashed var(--border); | |
| border-radius: 16px; | |
| padding: 40px 20px; | |
| text-align: center; | |
| background: rgba(255, 255, 255, 0.02); | |
| transition: all 0.3s ease; | |
| cursor: pointer; | |
| margin-bottom: 20px; | |
| } | |
| .upload-zone.drag-over { | |
| border-color: var(--primary); | |
| background: rgba(99, 102, 241, 0.1); | |
| } | |
| .upload-icon { | |
| font-size: 3rem; | |
| color: var(--text-muted); | |
| margin-bottom: 15px; | |
| } | |
| .upload-text { | |
| color: var(--text-main); | |
| font-weight: 500; | |
| } | |
| .upload-subtext { | |
| color: var(--text-muted); | |
| font-size: 0.9rem; | |
| margin-top: 5px; | |
| } | |
| #fileInput { | |
| display: none; | |
| } | |
| /* --- Document List --- */ | |
| .doc-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); | |
| gap: 15px; | |
| } | |
| .doc-card { | |
| background: var(--bg-card); | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 15px; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| text-align: center; | |
| transition: transform 0.2s, box-shadow 0.2s; | |
| position: relative; | |
| } | |
| .doc-card:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3); | |
| border-color: var(--primary); | |
| } | |
| .doc-icon { | |
| font-size: 2rem; | |
| margin-bottom: 10px; | |
| color: var(--primary); | |
| } | |
| .doc-name { | |
| font-size: 0.9rem; | |
| font-weight: 500; | |
| margin-bottom: 5px; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| width: 100%; | |
| } | |
| .doc-meta { | |
| font-size: 0.75rem; | |
| color: var(--text-muted); | |
| } | |
| .doc-actions { | |
| position: absolute; | |
| top: 5px; | |
| right: 5px; | |
| opacity: 0; | |
| transition: opacity 0.2s; | |
| } | |
| .doc-card:hover .doc-actions { | |
| opacity: 1; | |
| } | |
| .btn-icon { | |
| background: var(--bg-hover); | |
| border: none; | |
| color: var(--text-main); | |
| border-radius: 50%; | |
| width: 28px; | |
| height: 28px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| } | |
| .btn-icon:hover { | |
| background: var(--secondary); | |
| } | |
| /* --- AI Integration Hub --- */ | |
| .ai-grid { | |
| display: grid; | |
| grid-template-columns: 1fr; | |
| gap: 15px; | |
| } | |
| .ai-card { | |
| background: linear-gradient(135deg, var(--bg-card), rgba(30, 41, 59, 0.5)); | |
| border: 1px solid var(--border); | |
| border-radius: 16px; | |
| padding: 20px; | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| transition: transform 0.2s; | |
| } | |
| .ai-card:active { | |
| transform: scale(0.98); | |
| } | |
| .ai-avatar { | |
| width: 50px; | |
| height: 50px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.5rem; | |
| color: white; | |
| } | |
| .ai-info { | |
| flex: 1; | |
| } | |
| .ai-name { | |
| font-weight: 600; | |
| margin-bottom: 2px; | |
| } | |
| .ai-status { | |
| font-size: 0.8rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 5px; | |
| } | |
| .status-dot { | |
| width: 8px; | |
| height: 8px; | |
| background-color: var(--success); | |
| border-radius: 50%; | |
| box-shadow: 0 0 8px var(--success); | |
| } | |
| .btn-primary { | |
| background: var(--primary); | |
| color: white; | |
| border: none; | |
| padding: 10px 20px; | |
| border-radius: 8px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: background 0.2s; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .btn-primary:hover { | |
| background: var(--primary-dark); | |
| } | |
| /* --- Floating Action Button (FAB) --- */ | |
| .fab { | |
| position: fixed; | |
| bottom: calc(var(--nav-height) + 20px); | |
| right: 20px; | |
| width: 56px; | |
| height: 56px; | |
| border-radius: 50%; | |
| background: var(--primary); | |
| color: white; | |
| border: none; | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| z-index: 90; | |
| transition: transform 0.2s, background 0.2s; | |
| } | |
| .fab:hover { | |
| transform: scale(1.1); | |
| background: var(--primary-dark); | |
| } | |
| /* --- Bottom Navigation --- */ | |
| .bottom-nav { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| width: 100%; | |
| height: var(--nav-height); | |
| background: var(--bg-card); | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| justify-content: space-around; | |
| align-items: center; | |
| z-index: 100; | |
| } | |
| .nav-item { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| font-size: 0.75rem; | |
| gap: 4px; | |
| padding: 10px 20px; | |
| transition: color 0.2s; | |
| background: none; | |
| border: none; | |
| cursor: pointer; | |
| width: 100%; | |
| } | |
| .nav-item i { | |
| font-size: 1.5rem; | |
| } | |
| .nav-item.active { | |
| color: var(--primary); | |
| } | |
| /* --- Toast Notification --- */ | |
| .toast-container { | |
| position: fixed; | |
| top: 80px; | |
| right: 20px; | |
| z-index: 1000; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 10px; | |
| } | |
| .toast { | |
| background: var(--bg-card); | |
| border-left: 4px solid var(--primary); | |
| padding: 15px 20px; | |
| border-radius: 4px; | |
| box-shadow: 0 4px 12px rgba(0,0,0,0.3); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| animation: slideIn 0.3s ease; | |
| min-width: 250px; | |
| } | |
| @keyframes slideIn { | |
| from { transform: translateX(100%); opacity: 0; } | |
| to { transform: translateX(0); opacity: 1; } | |
| } | |
| /* --- Modal --- */ | |
| .modal-overlay { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: rgba(0, 0, 0, 0.7); | |
| backdrop-filter: blur(5px); | |
| z-index: 200; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: opacity 0.3s; | |
| } | |
| .modal-overlay.open { | |
| opacity: 1; | |
| pointer-events: all; | |
| } | |
| .modal { | |
| background: var(--bg-card); | |
| width: 90%; | |
| max-width: 400px; | |
| border-radius: 16px; | |
| padding: 25px; | |
| border: 1px solid var(--border); | |
| transform: scale(0.9); | |
| transition: transform 0.3s; | |
| } | |
| .modal-overlay.open .modal { | |
| transform: scale(1); | |
| } | |
| .modal h3 { | |
| margin-bottom: 15px; | |
| } | |
| .form-group { | |
| margin-bottom: 15px; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 5px; | |
| color: var(--text-muted); | |
| font-size: 0.9rem; | |
| } | |
| .form-group input, .form-group select, .form-group textarea { | |
| width: 100%; | |
| background: var(--bg-dark); | |
| border: 1px solid var(--border); | |
| padding: 12px; | |
| border-radius: 8px; | |
| color: var(--text-main); | |
| font-family: inherit; | |
| } | |
| .modal-actions { | |
| display: flex; | |
| justify-content: flex-end; | |
| gap: 10px; | |
| margin-top: 20px; | |
| } | |
| .btn-secondary { | |
| background: transparent; | |
| border: 1px solid var(--border); | |
| color: var(--text-main); | |
| padding: 10px 20px; | |
| border-radius: 8px; | |
| cursor: pointer; | |
| } | |
| /* --- Responsive Tweaks --- */ | |
| @media (min-width: 768px) { | |
| .doc-grid { | |
| grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); | |
| } | |
| .fab { | |
| width: 60px; | |
| height: 60px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- Header --> | |
| <header> | |
| <div class="brand"> | |
| <i class="ph ph-files"></i> | |
| <span>DocuHub AI</span> | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="built-with"> | |
| Built with anycoder | |
| </a> | |
| </header> | |
| <!-- Main Content Area --> | |
| <main> | |
| <!-- View 1: Document Storage --> | |
| <section id="view-storage" class="view-container active"> | |
| <h2>Meine Dokumente</h2> | |
| <div class="upload-zone" id="dropZone"> | |
| <i class="ph ph-cloud-arrow-up upload-icon"></i> | |
| <div class="upload-text">Hierher ziehen oder tippen</div> | |
| <div class="upload-subtext">PDF, JPG, PNG, TXT</div> | |
| <input type="file" id="fileInput" multiple> | |
| </div> | |
| <div class="doc-grid" id="docGrid"> | |
| <!-- Documents will be injected here via JS --> | |
| </div> | |
| </section> | |
| <!-- View 2: AI Integration Hub --> | |
| <section id="view-ai" class="view-container"> | |
| <h2>AI Integration Hub</h2> | |
| <p style="color: var(--text-muted); margin-bottom: 20px;"> | |
| Verbinden Sie KI-Modelle für automatisierte Analyse und Zusammenfassung. | |
| </p> | |
| <div class="ai-grid" id="aiGrid"> | |
| <!-- AI Cards will be injected here via JS --> | |
| </div> | |
| </section> | |
| <!-- View 3: Settings --> | |
| <section id="view-settings" class="view-container"> | |
| <h2>Einstellungen</h2> | |
| <div class="ai-card" style="cursor: default;"> | |
| <div class="ai-avatar" style="background: var(--bg-hover);"> | |
| <i class="ph ph-gear"></i> | |
| </div> | |
| <div class="ai-info"> | |
| <div class="ai-name">App Version</div> | |
| <div class="ai-status">v1.0.0 (Stable)</div> | |
| </div> | |
| </div> | |
| <div class="ai-card" style="cursor: default;"> | |
| <div class="ai-avatar" style="background: var(--bg-hover);"> | |
| <i class="ph ph-database"></i> | |
| </div> | |
| <div class="ai-info"> | |
| <div class="ai-name">Speicherstatus</div> | |
| <div class="ai-status">45% verbraucht</div> | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| <!-- Floating Action Button (Add Document) --> | |
| <button class="fab" id="fabAdd" onclick="triggerFileUpload()"> | |
| <i class="ph ph-plus"></i> | |
| </button> | |
| <!-- Bottom Navigation --> | |
| <nav class="bottom-nav"> | |
| <button class="nav-item active" onclick="switchView('view-storage', this)"> | |
| <i class="ph ph-files"></i> | |
| <span>Dokumente</span> | |
| </button> | |
| <button class="nav-item" onclick="switchView('view-ai', this)"> | |
| <i class="ph ph-robot"></i> | |
| <span>AI Hub</span> | |
| </button> | |
| <button class="nav-item" onclick="switchView('view-settings', this)"> | |
| <i class="ph ph-gear"></i> | |
| <span>Einstellungen</span> | |
| </button> | |
| </nav> | |
| <!-- Modal for Adding AI Connection --> | |
| <div class="modal-overlay" id="aiModal"> | |
| <div class="modal"> | |
| <h3>Neue KI-Verbindung</h3> | |
| <div class="form-group"> | |
| <label>Name des Assistenten</label> | |
| <input type="text" id="aiName" placeholder="z.B. Analyse-Bot"> | |
| </div> | |
| <div class="form-group"> | |
| <label>API Endpoint / Model</label> | |
| <select id="aiModel"> | |
| <option value="openai">OpenAI GPT-4</option> | |
| <option value="anthropic">Claude 3</option> | |
| <option value="local">Lokales Model (Ollama)</option> | |
| </select> | |
| </div> | |
| <div class="modal-actions"> | |
| <button class="btn-secondary" onclick="closeModal()">Abbrechen</button> | |
| <button class="btn-primary" onclick="saveAIConnection()">Verbinden</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Toast Container --> | |
| <div class="toast-container" id="toastContainer"></div> | |
| <script> | |
| // --- State Management --- | |
| let documents = [ | |
| { id: 1, name: "Projekt_Plan.pdf", type: "pdf", date: "Heute" }, | |
| { id: 2, name: "Rechnung_123.jpg", type: "image", date: "Gestern" }, | |
| { id: 3, name: "Meeting_Notizen.txt", type: "text", date: "01.10.2023" } | |
| ]; | |
| let aiConnections = [ | |
| { id: 1, name: "ChatGPT", model: "GPT-4", active: true }, | |
| { id: 2, name: "Claude", model: "Claude 3 Opus", active: false } | |
| ]; | |
| // --- DOM Elements --- | |
| const dropZone = document.getElementById('dropZone'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const docGrid = document.getElementById('docGrid'); | |
| const aiGrid = document.getElementById('aiGrid'); | |
| const aiModal = document.getElementById('aiModal'); | |
| // --- Initialization --- | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderDocuments(); | |
| renderAIConnections(); | |
| setupDragAndDrop(); | |
| }); | |
| // --- Navigation Logic --- | |
| function switchView(viewId, navBtn) { | |
| // Hide all views | |
| document.querySelectorAll('.view-container').forEach(el => { | |
| el.classList.remove('active'); | |
| }); | |
| // Show target view | |
| document.getElementById(viewId).classList.add('active'); | |
| // Update Nav Icons | |
| document.querySelectorAll('.nav-item').forEach(el => { | |
| el.classList.remove('active'); | |
| }); | |
| if(navBtn) navBtn.classList.add('active'); | |
| } | |
| // --- File Upload Logic --- | |
| function triggerFileUpload() { | |
| fileInput.click(); | |
| } | |
| function setupDragAndDrop() { | |
| // Prevent default browser behavior | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, preventDefaults, false); | |
| document.body.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| // Highlight drop zone | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, () => dropZone.classList.add('drag-over'), false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, () => dropZone.classList.remove('drag-over'), false); | |
| }); | |
| // Handle Drop | |
| dropZone.addEventListener('drop', handleDrop, false); | |
| // Handle Click to Upload | |
| dropZone.addEventListener('click', () => fileInput.click()); | |
| fileInput.addEventListener('change', (e) => handleFiles(e.target.files)); | |
| } | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleFiles(files); | |
| } | |
| function handleFiles(files) { | |
| ([...files]).forEach(file => { | |
| // Check if it's a file type we care about | |
| if(file.type) { | |
| const type = file.type.split('/')[0]; | |
| const newDoc = { | |
| id: Date.now(), | |
| name: file.name, | |
| type: type === 'image' ? 'image' : 'file', | |
| date: "Gerade eben" | |
| }; | |
| documents.unshift(newDoc); // Add to top | |
| showToast(`Dokument "${file.name}" hochgeladen`); | |
| } | |
| }); | |
| renderDocuments(); | |
| } | |
| // --- Rendering Logic --- | |
| function renderDocuments() { | |
| docGrid.innerHTML = ''; | |
| documents.forEach(doc => { | |
| let iconClass = 'ph-file'; | |
| let color = 'var(--text-muted)'; | |
| if(doc.type === 'pdf') { iconClass = 'ph-file-pdf'; color = '#ef4444'; } | |
| if(doc.type === 'image') { iconClass = 'ph-image'; color = '#ec4899'; } | |
| const card = document.createElement('div'); | |
| card.className = 'doc-card'; | |
| card.innerHTML = ` | |
| <div class="doc-actions"> | |
| <button class="btn-icon" onclick="deleteDoc(${doc.id})"> | |
| <i class="ph ph-trash"></i> | |
| </button> | |
| </div> | |
| <i class="ph ${iconClass} doc-icon" style="color: ${color}"></i> | |
| <div class="doc-name" title="${doc.name}">${doc.name}</div> | |
| <div class="doc-meta">${doc.date}</div> | |
| `; | |
| docGrid.appendChild(card); | |
| }); | |
| } | |
| function deleteDoc(id) { | |
| documents = documents.filter(d => d.id !== id); | |
| renderDocuments(); | |
| showToast('Dokument gelöscht'); | |
| } | |
| function renderAIConnections() { | |
| aiGrid.innerHTML = ''; | |
| aiConnections.forEach(ai => { | |
| const card = document.createElement('div'); | |
| card.className = 'ai-card'; | |
| // Determine Icon based on provider | |
| let icon = 'ph-robot'; | |
| let bg = 'var(--primary)'; | |
| if(ai.model.includes('Claude')) { icon = 'ph-brain'; bg = '#d97706'; } | |
| if(ai.model.includes('Lokal')) { icon = 'ph-cpu'; bg = '#059669'; } | |
| card.innerHTML = ` | |
| <div class="ai-avatar" style="background: ${bg}"> | |
| <i class="ph ${icon}"></i> | |
| </div> | |
| <div class="ai-info"> | |
| <div class="ai-name">${ai.name}</div> | |
| <div class="ai-status"> | |
| <div class="status-dot"></div> | |
| ${ai.active ? 'Aktiv' : 'Inaktiv'} | |
| </div> | |
| </div> | |
| <button class="btn-icon" onclick="toggleAI(${ai.id})"> | |
| <i class="ph ${ai.active ? 'ph-power' : 'ph-power'}"></i> | |
| </button> | |
| <button class="btn-icon" style="background:transparent; opacity:0.5; pointer-events:none"> | |
| <i class="ph ph-dots-three-vertical"></i> | |
| </button> | |
| `; | |
| aiGrid.appendChild(card); | |
| }); | |
| } | |
| // --- AI Connection Logic --- | |
| function openModal() { | |
| aiModal.classList.add('open'); | |
| } | |
| function closeModal() { | |
| aiModal.classList.remove('open'); | |
| } | |
| function saveAIConnection() { | |
| const name = document.getElementById('aiName').value; | |
| const model = document.getElementById('aiModel').value; | |
| if(!name) { | |
| showToast('Bitte geben Sie einen Namen ein'); | |
| return; | |
| } | |
| aiConnections.push({ | |
| id: Date.now(), | |
| name: name, | |
| model: model, | |
| active: true | |
| }); | |
| renderAIConnections(); | |
| closeModal(); | |
| showToast(`KI-Verbindung "${name}" erstellt`); | |
| } | |
| function toggleAI(id) { | |
| const ai = aiConnections.find(a => a.id === id); | |
| if(ai) { | |
| ai.active = !ai.active; | |
| renderAIConnections(); | |
| showToast(`KI "${ai.name}" ${ai.active ? 'aktiviert' : 'deaktiviert'}`); | |
| } | |
| } | |
| // --- Utilities --- | |
| function showToast(message) { | |
| const container = document.getElementById('toastContainer'); | |
| const toast = document.createElement('div'); | |
| toast.className = 'toast'; | |
| toast.innerHTML = `<i class="ph ph-check-circle" style="color: var(--success); font-size: 1.2rem;"></i> ${message}`; | |
| container.appendChild(toast); | |
| // Remove after 3 seconds | |
| setTimeout(() => { | |
| toast.style.opacity = '0'; | |
| toast.style.transform = 'translateX(100%)'; | |
| setTimeout(() => toast.remove(), 300); | |
| }, 3000); | |
| } | |
| </script> | |
| </body> | |
| </html> |