aiWeb / index.html
benkada's picture
Update index.html
a8335ea verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Smart Analyzer Pro</title>
<style>
:root {
--primary-color: #4361ee;
--secondary-color: #f1f5f9;
--accent-color: #3f37c9;
--text-color: #333;
--light-text: #666;
--btn-color: #4361ee;
--btn-hover: #3f37c9;
--card-bg: #fff;
--card-shadow: rgba(0, 0, 0, 0.08);
--border-radius: 10px;
--transition: 0.3s;
--max-width: 1200px;
}
* { box-sizing: border-box; }
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: var(--text-color);
background: var(--secondary-color);
margin: 0;
padding: 0;
min-height: 100vh;
}
.app-header {
background: var(--primary-color);
color: white;
padding: 20px 0;
text-align: center;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 40px;
}
.app-title {
margin: 0;
font-size: 2.5rem;
}
.app-subtitle {
margin: 10px 0 0;
font-weight: normal;
opacity: 0.9;
}
.container {
width: 92%;
max-width: var(--max-width);
margin: 0 auto;
padding: 0 20px 40px;
}
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 30px;
}
.section {
background: var(--card-bg);
padding: 25px;
border-radius: var(--border-radius);
box-shadow: 0 5px 15px var(--card-shadow);
transition: transform var(--transition), box-shadow var(--transition);
position: relative;
overflow: hidden;
}
.section:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
}
.section::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 5px;
background: var(--primary-color);
}
h2 {
margin-top: 0;
color: var(--primary-color);
font-size: 1.5rem;
padding-bottom: 10px;
border-bottom: 2px solid var(--secondary-color);
}
.icon {
display: inline-block;
margin-right: 8px;
vertical-align: middle;
}
.file-input-wrapper {
position: relative;
margin-top: 20px;
}
.file-input-label {
display: block;
background: var(--secondary-color);
border: 2px dashed #ccc;
border-radius: var(--border-radius);
padding: 25px 15px;
text-align: center;
cursor: pointer;
transition: all var(--transition);
}
.file-input-label:hover {
border-color: var(--primary-color);
background: #e8eeff;
}
.file-input {
position: absolute;
left: 0;
top: 0;
opacity: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.file-name {
margin-top: 10px;
font-size: 0.9rem;
color: var(--light-text);
min-height: 20px;
}
input[type="text"] {
width: 100%;
padding: 12px 15px;
margin-top: 15px;
border: 1px solid #ddd;
border-radius: var(--border-radius);
font-size: 1rem;
transition: border-color var(--transition);
}
input[type="text"]:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15);
}
.btn {
background: var(--btn-color);
color: white;
border: none;
border-radius: var(--border-radius);
padding: 12px 20px;
font-size: 1rem;
cursor: pointer;
transition: all var(--transition);
display: block;
width: 100%;
margin-top: 20px;
font-weight: 600;
}
.btn:hover {
background: var(--btn-hover);
transform: translateY(-2px);
}
.btn:active {
transform: translateY(0);
}
.results {
margin-top: 25px;
padding: 20px;
background: var(--secondary-color);
border-radius: var(--border-radius);
border: 1px solid #ddd;
min-height: 100px;
position: relative;
}
.loader {
display: none;
text-align: center;
padding: 20px 0;
}
.loader::after {
content: '';
display: inline-block;
width: 30px;
height: 30px;
border: 3px solid var(--secondary-color);
border-radius: 50%;
border-top-color: var(--primary-color);
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.processing .loader {
display: block;
}
.processing .result-content {
display: none;
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
</style>
</head>
<body>
<header class="app-header">
<h1 class="app-title">Smart Analyzer Pro</h1>
<p class="app-subtitle">Analyze documents, answer questions, and interpret images with AI</p>
</header>
<div class="container">
<div class="grid">
<div class="section">
<h2><span class="icon">πŸ“„</span>Summarize Document</h2>
<div class="file-input-wrapper">
<label class="file-input-label">
<span>Drop your document here or click to browse</span>
<input type="file" id="summary-file" class="file-input" accept=".pdf,.docx,.txt">
</label>
<div id="summary-file-name" class="file-name"></div>
</div>
<button id="summarize-btn" class="btn">Generate Summary</button>
<div id="summary-result" class="results">
<div class="loader"></div>
<div class="result-content">Your summary will appear here.</div>
</div>
</div>
<div class="section">
<h2><span class="icon">❓</span>Ask a Question</h2>
<div class="file-input-wrapper">
<label class="file-input-label">
<span>Drop your file here or click to browse</span>
<input type="file" id="qa-file" class="file-input" accept=".pdf,.docx,.txt,image/*">
</label>
<div id="qa-file-name" class="file-name"></div>
</div>
<input type="text" id="qa-question" placeholder="Type your question about the document...">
<button id="qa-btn" class="btn">Get Answer</button>
<div id="qa-result" class="results">
<div class="loader"></div>
<div class="result-content">Answer will appear here.</div>
</div>
</div>
<div class="section">
<h2><span class="icon">πŸ–ΌοΈ</span>Analyze Image</h2>
<div class="file-input-wrapper">
<label class="file-input-label">
<span>Drop your image here or click to browse</span>
<input type="file" id="image-file" class="file-input" accept="image/*">
</label>
<div id="image-file-name" class="file-name"></div>
</div>
<button id="image-btn" class="btn">Generate Description</button>
<div id="image-result" class="results">
<div class="loader"></div>
<div class="result-content">Image description will appear here.</div>
</div>
</div>
</div>
</div>
<script>
// Show file name when selected
document.querySelectorAll('.file-input').forEach(input => {
input.addEventListener('change', function() {
const fileNameElement = document.getElementById(this.id + '-name');
fileNameElement.textContent = this.files[0] ? this.files[0].name : '';
});
});
async function sendData(url, fileInputId, extraData, resultId) {
const fileInput = document.getElementById(fileInputId);
const file = fileInput.files[0];
const resultElement = document.getElementById(resultId);
const resultContent = resultElement.querySelector('.result-content');
if (!file) {
resultContent.textContent = 'Please select a file.';
return;
}
const formData = new FormData();
formData.append(fileInputId.includes('image') ? 'image' : 'file', file);
if (extraData) {
for (const [key, value] of Object.entries(extraData)) {
formData.append(key, value);
}
}
// Show loading state
resultElement.classList.add('processing');
try {
const res = await fetch(url, { method: 'POST', body: formData });
const data = await res.json();
// Update result content
resultContent.textContent = data.result || data.summary || data.answer ||
data.description || data.error || JSON.stringify(data);
} catch (err) {
resultContent.textContent = 'Error: ' + err.message;
} finally {
// Hide loading state
resultElement.classList.remove('processing');
}
}
document.getElementById('summarize-btn').addEventListener('click', () => {
sendData('/api/summarize', 'summary-file', null, 'summary-result');
});
document.getElementById('qa-btn').addEventListener('click', () => {
const question = document.getElementById('qa-question').value.trim();
if (!question) {
document.getElementById('qa-result').querySelector('.result-content').textContent = 'Please enter a question.';
return;
}
sendData('/api/qa', 'qa-file', { question }, 'qa-result');
});
document.getElementById('image-btn').addEventListener('click', () => {
sendData('/api/caption', 'image-file', null, 'image-result');
});
</script>
</body>
</html>