Update templates/index.html
Browse files- templates/index.html +50 -31
templates/index.html
CHANGED
|
@@ -27,13 +27,12 @@
|
|
| 27 |
}
|
| 28 |
|
| 29 |
html {
|
| 30 |
-
/* Améliore la fluidité du défilement */
|
| 31 |
scroll-behavior: smooth;
|
| 32 |
}
|
| 33 |
|
| 34 |
body {
|
| 35 |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
| 36 |
-
max-width: 600px;
|
| 37 |
margin: 0 auto;
|
| 38 |
padding: var(--spacing-unit);
|
| 39 |
line-height: 1.6;
|
|
@@ -47,7 +46,6 @@
|
|
| 47 |
}
|
| 48 |
|
| 49 |
.header h1 {
|
| 50 |
-
/* MODIFIÉ: Typographie réactive pour s'adapter à toutes les tailles d'écrans */
|
| 51 |
font-size: clamp(1.75rem, 7vw, 2.5rem);
|
| 52 |
color: #2c3e50;
|
| 53 |
margin-bottom: calc(var(--spacing-unit) * 0.25);
|
|
@@ -58,12 +56,10 @@
|
|
| 58 |
color: #555;
|
| 59 |
}
|
| 60 |
|
| 61 |
-
/* <!-- SUPPRIMÉ: Le conteneur du bouton Telegram a été retiré --> */
|
| 62 |
-
|
| 63 |
.container {
|
| 64 |
background-color: var(--card-bg);
|
| 65 |
padding: calc(var(--spacing-unit) * 1.5);
|
| 66 |
-
border-radius: 12px;
|
| 67 |
box-shadow: var(--shadow);
|
| 68 |
margin-bottom: calc(var(--spacing-unit) * 2);
|
| 69 |
}
|
|
@@ -81,7 +77,6 @@
|
|
| 81 |
gap: var(--spacing-unit);
|
| 82 |
}
|
| 83 |
|
| 84 |
-
/* MODIFIÉ: Amélioration sémantique et UX des boutons radio */
|
| 85 |
.radio-option label {
|
| 86 |
display: flex;
|
| 87 |
align-items: flex-start;
|
|
@@ -103,7 +98,6 @@
|
|
| 103 |
}
|
| 104 |
|
| 105 |
.radio-option input[type="radio"] {
|
| 106 |
-
/* Caché car on stylise le label à la place */
|
| 107 |
display: none;
|
| 108 |
}
|
| 109 |
|
|
@@ -118,7 +112,6 @@
|
|
| 118 |
.radio-label { font-weight: 500; display: block; }
|
| 119 |
.radio-description { font-size: 0.9rem; color: #666; }
|
| 120 |
|
| 121 |
-
|
| 122 |
.upload-section {
|
| 123 |
border: 2px dashed var(--border-color);
|
| 124 |
padding: calc(var(--spacing-unit) * 2);
|
|
@@ -150,11 +143,11 @@
|
|
| 150 |
|
| 151 |
.button {
|
| 152 |
width: 100%;
|
| 153 |
-
padding: 0.9rem 1rem;
|
| 154 |
border: none;
|
| 155 |
border-radius: 8px;
|
| 156 |
-
font-size: 1.1rem;
|
| 157 |
-
font-weight: 600;
|
| 158 |
cursor: pointer;
|
| 159 |
transition: all 0.3s ease;
|
| 160 |
margin-top: calc(var(--spacing-unit) * 0.5);
|
|
@@ -168,7 +161,7 @@
|
|
| 168 |
.button:hover:not(:disabled) { transform: translateY(-2px); background-color: var(--primary-hover); }
|
| 169 |
.button:disabled { background-color: #bdc3c7; cursor: not-allowed; box-shadow: none; }
|
| 170 |
|
| 171 |
-
.clear-button { background-color: #7f8c8d; }
|
| 172 |
.clear-button:hover:not(:disabled) { background-color: #95a5a6; }
|
| 173 |
|
| 174 |
.download-button { background-color: var(--secondary-color); }
|
|
@@ -182,7 +175,18 @@
|
|
| 182 |
.status.error { color: var(--danger-color); }
|
| 183 |
.status.completed { color: var(--secondary-color); }
|
| 184 |
|
| 185 |
-
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
.processing-notice {
|
| 187 |
background-color: #eaf5ff;
|
| 188 |
border-left: 4px solid var(--primary-color);
|
|
@@ -200,7 +204,7 @@
|
|
| 200 |
#history-container h2 { text-align:center; margin-bottom: var(--spacing-unit); color: #2c3e50;}
|
| 201 |
#history-list { list-style: none; padding: 0; display: flex; flex-direction: column; gap: calc(var(--spacing-unit)*0.75);}
|
| 202 |
.history-item { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-unit); background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 8px; transition: box-shadow 0.2s; gap: var(--spacing-unit); }
|
| 203 |
-
.history-info { flex-grow: 1; min-width: 0; }
|
| 204 |
.history-filename { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
| 205 |
.history-status { font-size: 0.85rem; }
|
| 206 |
.history-status-pending { color: #f39c12; } .history-status-completed { color: var(--secondary-color); } .history-status-error { color: var(--danger-color); }
|
|
@@ -213,24 +217,21 @@
|
|
| 213 |
</head>
|
| 214 |
<body>
|
| 215 |
<div class="header">
|
| 216 |
-
<h1>🖼️ Science (Math, Physique, Chimie)
|
| 217 |
<p class="subtitle">Avec Mariam, votre assistante IA</p>
|
| 218 |
</div>
|
| 219 |
|
| 220 |
-
<!-- SUPPRIMÉ : Le bouton pour rejoindre le groupe Telegram a été enlevé. -->
|
| 221 |
-
|
| 222 |
<div class="container">
|
| 223 |
<div class="style-selection">
|
| 224 |
<h3>🎨 Choisissez le style de résolution</h3>
|
| 225 |
<div class="radio-group">
|
| 226 |
-
<!-- MODIFIÉ: Structure sémantique et accessible des boutons radio -->
|
| 227 |
<div class="radio-option">
|
| 228 |
<input type="radio" id="style-light" name="resolution-style" value="light">
|
| 229 |
<label for="style-light" class="radio-content-wrapper">
|
| 230 |
<div class="radio-icon">📝</div>
|
| 231 |
<div class="radio-content">
|
| 232 |
<span class="radio-label">Résolution Light</span>
|
| 233 |
-
<div class="radio-description">Simple et
|
| 234 |
</div>
|
| 235 |
</label>
|
| 236 |
</div>
|
|
@@ -264,8 +265,13 @@
|
|
| 264 |
<button id="solve-button" class="button" disabled>🔍 Résoudre</button>
|
| 265 |
|
| 266 |
<div id="solving-container">
|
| 267 |
-
<!--
|
| 268 |
-
<div class="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
<p>⏳ La génération a commencé...</p>
|
| 270 |
<small>Cela peut prendre quelques minutes. Vous pouvez fermer cette page et revenir plus tard, votre résultat apparaîtra dans l'historique ci-dessous.</small>
|
| 271 |
</div>
|
|
@@ -286,8 +292,6 @@
|
|
| 286 |
</div>
|
| 287 |
|
| 288 |
<script>
|
| 289 |
-
// Le JavaScript reste identique car il est déjà bien conçu pour gérer cette logique.
|
| 290 |
-
// Les modifications sont purement dans le HTML et le CSS.
|
| 291 |
document.addEventListener('DOMContentLoaded', function() {
|
| 292 |
const uploadSection = document.getElementById('upload-section');
|
| 293 |
const fileInput = document.getElementById('file-input');
|
|
@@ -303,6 +307,10 @@
|
|
| 303 |
const cooldownTimer = document.getElementById('cooldown-timer');
|
| 304 |
const historyList = document.getElementById('history-list');
|
| 305 |
const clearHistoryButton = document.getElementById('clear-history-button');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 306 |
|
| 307 |
let selectedFiles = [];
|
| 308 |
let cooldownEndTime = 0;
|
|
@@ -390,9 +398,6 @@
|
|
| 390 |
});
|
| 391 |
}
|
| 392 |
|
| 393 |
-
// La fonction selectStyle n'est plus nécessaire grâce à l'utilisation des <label>
|
| 394 |
-
// window.selectStyle = (style) => document.getElementById(`style-${style}`).checked = true;
|
| 395 |
-
|
| 396 |
function checkCooldownOnLoad() {
|
| 397 |
const savedCooldown = localStorage.getItem('mariamCooldownEndTime');
|
| 398 |
if (savedCooldown && parseInt(savedCooldown) > Date.now()) {
|
|
@@ -491,13 +496,15 @@
|
|
| 491 |
|
| 492 |
startCooldown();
|
| 493 |
solveButton.disabled = true;
|
| 494 |
-
solveButton.textContent = '⏳
|
| 495 |
|
|
|
|
| 496 |
solvingContainer.style.display = 'block';
|
|
|
|
|
|
|
| 497 |
responseContainer.style.display = 'none';
|
| 498 |
downloadButton.style.display = 'none';
|
| 499 |
-
statusElement.
|
| 500 |
-
statusElement.textContent = 'Préparation...';
|
| 501 |
responseDiv.innerHTML = '';
|
| 502 |
|
| 503 |
const formData = new FormData();
|
|
@@ -506,6 +513,11 @@
|
|
| 506 |
|
| 507 |
fetch('/solve', { method: 'POST', body: formData })
|
| 508 |
.then(response => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 509 |
if (!response.ok) return response.json().then(err => { throw new Error(err.error) });
|
| 510 |
return response.json();
|
| 511 |
})
|
|
@@ -520,7 +532,12 @@
|
|
| 520 |
statusElement.textContent = 'Traitement en arrière-plan...';
|
| 521 |
listenToTask(task_id);
|
| 522 |
})
|
| 523 |
-
.catch(error =>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 524 |
});
|
| 525 |
|
| 526 |
function listenToTask(taskId) {
|
|
@@ -537,6 +554,7 @@
|
|
| 537 |
statusElement.textContent = `Statut: ${data.status}`;
|
| 538 |
|
| 539 |
if (data.status === 'completed') {
|
|
|
|
| 540 |
statusElement.className = 'status completed';
|
| 541 |
statusElement.textContent = 'Traitement terminé ! 🎉';
|
| 542 |
responseDiv.innerHTML = `<p style="color: #2ecc71; text-align: center;">Votre PDF est prêt.</p>`;
|
|
@@ -545,6 +563,7 @@
|
|
| 545 |
responseContainer.style.display = 'block';
|
| 546 |
eventSource.close();
|
| 547 |
} else if (data.status === 'error') {
|
|
|
|
| 548 |
handleError(data.error || 'Une erreur inattendue est survenue.', taskId);
|
| 549 |
eventSource.close();
|
| 550 |
}
|
|
|
|
| 27 |
}
|
| 28 |
|
| 29 |
html {
|
|
|
|
| 30 |
scroll-behavior: smooth;
|
| 31 |
}
|
| 32 |
|
| 33 |
body {
|
| 34 |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
| 35 |
+
max-width: 600px;
|
| 36 |
margin: 0 auto;
|
| 37 |
padding: var(--spacing-unit);
|
| 38 |
line-height: 1.6;
|
|
|
|
| 46 |
}
|
| 47 |
|
| 48 |
.header h1 {
|
|
|
|
| 49 |
font-size: clamp(1.75rem, 7vw, 2.5rem);
|
| 50 |
color: #2c3e50;
|
| 51 |
margin-bottom: calc(var(--spacing-unit) * 0.25);
|
|
|
|
| 56 |
color: #555;
|
| 57 |
}
|
| 58 |
|
|
|
|
|
|
|
| 59 |
.container {
|
| 60 |
background-color: var(--card-bg);
|
| 61 |
padding: calc(var(--spacing-unit) * 1.5);
|
| 62 |
+
border-radius: 12px;
|
| 63 |
box-shadow: var(--shadow);
|
| 64 |
margin-bottom: calc(var(--spacing-unit) * 2);
|
| 65 |
}
|
|
|
|
| 77 |
gap: var(--spacing-unit);
|
| 78 |
}
|
| 79 |
|
|
|
|
| 80 |
.radio-option label {
|
| 81 |
display: flex;
|
| 82 |
align-items: flex-start;
|
|
|
|
| 98 |
}
|
| 99 |
|
| 100 |
.radio-option input[type="radio"] {
|
|
|
|
| 101 |
display: none;
|
| 102 |
}
|
| 103 |
|
|
|
|
| 112 |
.radio-label { font-weight: 500; display: block; }
|
| 113 |
.radio-description { font-size: 0.9rem; color: #666; }
|
| 114 |
|
|
|
|
| 115 |
.upload-section {
|
| 116 |
border: 2px dashed var(--border-color);
|
| 117 |
padding: calc(var(--spacing-unit) * 2);
|
|
|
|
| 143 |
|
| 144 |
.button {
|
| 145 |
width: 100%;
|
| 146 |
+
padding: 0.9rem 1rem;
|
| 147 |
border: none;
|
| 148 |
border-radius: 8px;
|
| 149 |
+
font-size: 1.1rem;
|
| 150 |
+
font-weight: 600;
|
| 151 |
cursor: pointer;
|
| 152 |
transition: all 0.3s ease;
|
| 153 |
margin-top: calc(var(--spacing-unit) * 0.5);
|
|
|
|
| 161 |
.button:hover:not(:disabled) { transform: translateY(-2px); background-color: var(--primary-hover); }
|
| 162 |
.button:disabled { background-color: #bdc3c7; cursor: not-allowed; box-shadow: none; }
|
| 163 |
|
| 164 |
+
.clear-button { background-color: #7f8c8d; }
|
| 165 |
.clear-button:hover:not(:disabled) { background-color: #95a5a6; }
|
| 166 |
|
| 167 |
.download-button { background-color: var(--secondary-color); }
|
|
|
|
| 175 |
.status.error { color: var(--danger-color); }
|
| 176 |
.status.completed { color: var(--secondary-color); }
|
| 177 |
|
| 178 |
+
/* NOUVEAU: Message d'upload en cours */
|
| 179 |
+
.upload-notice {
|
| 180 |
+
background-color: #fff3cd;
|
| 181 |
+
border-left: 4px solid #ffc107;
|
| 182 |
+
padding: var(--spacing-unit);
|
| 183 |
+
margin: var(--spacing-unit) 0;
|
| 184 |
+
border-radius: 8px;
|
| 185 |
+
text-align: center;
|
| 186 |
+
}
|
| 187 |
+
.upload-notice p { margin: 0; font-weight: 600; color: #856404; }
|
| 188 |
+
.upload-notice small { color: #6c5d03; }
|
| 189 |
+
|
| 190 |
.processing-notice {
|
| 191 |
background-color: #eaf5ff;
|
| 192 |
border-left: 4px solid var(--primary-color);
|
|
|
|
| 204 |
#history-container h2 { text-align:center; margin-bottom: var(--spacing-unit); color: #2c3e50;}
|
| 205 |
#history-list { list-style: none; padding: 0; display: flex; flex-direction: column; gap: calc(var(--spacing-unit)*0.75);}
|
| 206 |
.history-item { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-unit); background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 8px; transition: box-shadow 0.2s; gap: var(--spacing-unit); }
|
| 207 |
+
.history-info { flex-grow: 1; min-width: 0; }
|
| 208 |
.history-filename { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
| 209 |
.history-status { font-size: 0.85rem; }
|
| 210 |
.history-status-pending { color: #f39c12; } .history-status-completed { color: var(--secondary-color); } .history-status-error { color: var(--danger-color); }
|
|
|
|
| 217 |
</head>
|
| 218 |
<body>
|
| 219 |
<div class="header">
|
| 220 |
+
<h1>🖼️ Science (Math, Physique, Chimie) 🧪</h1>
|
| 221 |
<p class="subtitle">Avec Mariam, votre assistante IA</p>
|
| 222 |
</div>
|
| 223 |
|
|
|
|
|
|
|
| 224 |
<div class="container">
|
| 225 |
<div class="style-selection">
|
| 226 |
<h3>🎨 Choisissez le style de résolution</h3>
|
| 227 |
<div class="radio-group">
|
|
|
|
| 228 |
<div class="radio-option">
|
| 229 |
<input type="radio" id="style-light" name="resolution-style" value="light">
|
| 230 |
<label for="style-light" class="radio-content-wrapper">
|
| 231 |
<div class="radio-icon">📝</div>
|
| 232 |
<div class="radio-content">
|
| 233 |
<span class="radio-label">Résolution Light</span>
|
| 234 |
+
<div class="radio-description">Simple et épurée, pour une lecture rapide.</div>
|
| 235 |
</div>
|
| 236 |
</label>
|
| 237 |
</div>
|
|
|
|
| 265 |
<button id="solve-button" class="button" disabled>🔍 Résoudre</button>
|
| 266 |
|
| 267 |
<div id="solving-container">
|
| 268 |
+
<!-- NOUVEAU: Message d'upload en cours -->
|
| 269 |
+
<div id="upload-notice" class="upload-notice" style="display: none;">
|
| 270 |
+
<p>📤 Envoi des fichiers en cours...</p>
|
| 271 |
+
<small>Veuillez patienter pendant le téléchargement de vos fichiers vers le serveur.</small>
|
| 272 |
+
</div>
|
| 273 |
+
|
| 274 |
+
<div id="processing-notice" class="processing-notice" style="display: none;">
|
| 275 |
<p>⏳ La génération a commencé...</p>
|
| 276 |
<small>Cela peut prendre quelques minutes. Vous pouvez fermer cette page et revenir plus tard, votre résultat apparaîtra dans l'historique ci-dessous.</small>
|
| 277 |
</div>
|
|
|
|
| 292 |
</div>
|
| 293 |
|
| 294 |
<script>
|
|
|
|
|
|
|
| 295 |
document.addEventListener('DOMContentLoaded', function() {
|
| 296 |
const uploadSection = document.getElementById('upload-section');
|
| 297 |
const fileInput = document.getElementById('file-input');
|
|
|
|
| 307 |
const cooldownTimer = document.getElementById('cooldown-timer');
|
| 308 |
const historyList = document.getElementById('history-list');
|
| 309 |
const clearHistoryButton = document.getElementById('clear-history-button');
|
| 310 |
+
|
| 311 |
+
// NOUVEAU: Références aux nouveaux éléments
|
| 312 |
+
const uploadNotice = document.getElementById('upload-notice');
|
| 313 |
+
const processingNotice = document.getElementById('processing-notice');
|
| 314 |
|
| 315 |
let selectedFiles = [];
|
| 316 |
let cooldownEndTime = 0;
|
|
|
|
| 398 |
});
|
| 399 |
}
|
| 400 |
|
|
|
|
|
|
|
|
|
|
| 401 |
function checkCooldownOnLoad() {
|
| 402 |
const savedCooldown = localStorage.getItem('mariamCooldownEndTime');
|
| 403 |
if (savedCooldown && parseInt(savedCooldown) > Date.now()) {
|
|
|
|
| 496 |
|
| 497 |
startCooldown();
|
| 498 |
solveButton.disabled = true;
|
| 499 |
+
solveButton.textContent = '⏳ Envoi en cours...';
|
| 500 |
|
| 501 |
+
// MODIFIÉ: Affichage immédiat du conteneur avec message d'upload
|
| 502 |
solvingContainer.style.display = 'block';
|
| 503 |
+
uploadNotice.style.display = 'block'; // Affiche le message d'upload
|
| 504 |
+
processingNotice.style.display = 'none'; // Cache le message de traitement
|
| 505 |
responseContainer.style.display = 'none';
|
| 506 |
downloadButton.style.display = 'none';
|
| 507 |
+
statusElement.textContent = ''; // Pas de statut tant que l'upload n'est pas fini
|
|
|
|
| 508 |
responseDiv.innerHTML = '';
|
| 509 |
|
| 510 |
const formData = new FormData();
|
|
|
|
| 513 |
|
| 514 |
fetch('/solve', { method: 'POST', body: formData })
|
| 515 |
.then(response => {
|
| 516 |
+
// MODIFIÉ: Masquer le message d'upload et afficher le message de traitement
|
| 517 |
+
uploadNotice.style.display = 'none';
|
| 518 |
+
processingNotice.style.display = 'block';
|
| 519 |
+
statusElement.textContent = 'Préparation...'; // Maintenant on peut afficher ce message
|
| 520 |
+
|
| 521 |
if (!response.ok) return response.json().then(err => { throw new Error(err.error) });
|
| 522 |
return response.json();
|
| 523 |
})
|
|
|
|
| 532 |
statusElement.textContent = 'Traitement en arrière-plan...';
|
| 533 |
listenToTask(task_id);
|
| 534 |
})
|
| 535 |
+
.catch(error => {
|
| 536 |
+
// MODIFIÉ: En cas d'erreur, masquer les messages d'upload/processing
|
| 537 |
+
uploadNotice.style.display = 'none';
|
| 538 |
+
processingNotice.style.display = 'none';
|
| 539 |
+
handleError(error.message);
|
| 540 |
+
});
|
| 541 |
});
|
| 542 |
|
| 543 |
function listenToTask(taskId) {
|
|
|
|
| 554 |
statusElement.textContent = `Statut: ${data.status}`;
|
| 555 |
|
| 556 |
if (data.status === 'completed') {
|
| 557 |
+
processingNotice.style.display = 'none';
|
| 558 |
statusElement.className = 'status completed';
|
| 559 |
statusElement.textContent = 'Traitement terminé ! 🎉';
|
| 560 |
responseDiv.innerHTML = `<p style="color: #2ecc71; text-align: center;">Votre PDF est prêt.</p>`;
|
|
|
|
| 563 |
responseContainer.style.display = 'block';
|
| 564 |
eventSource.close();
|
| 565 |
} else if (data.status === 'error') {
|
| 566 |
+
processingNotice.style.display = 'none';
|
| 567 |
handleError(data.error || 'Une erreur inattendue est survenue.', taskId);
|
| 568 |
eventSource.close();
|
| 569 |
}
|