Spaces:
Running
Running
Update templates/philosophie.html
Browse files- templates/philosophie.html +433 -114
templates/philosophie.html
CHANGED
|
@@ -108,6 +108,28 @@
|
|
| 108 |
transform: translateY(0) translateZ(0);
|
| 109 |
}
|
| 110 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
/* Styles pour Select2 */
|
| 113 |
.select2-container--default .select2-selection--single {
|
|
@@ -153,6 +175,131 @@
|
|
| 153 |
summary::-webkit-details-marker {
|
| 154 |
display: none;
|
| 155 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
/* Optimisations mobiles */
|
| 158 |
@media (max-width: 640px) {
|
|
@@ -179,6 +326,15 @@
|
|
| 179 |
.animate-fadeIn {
|
| 180 |
animation-duration: 0.2s;
|
| 181 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
}
|
| 183 |
|
| 184 |
/* Conteneur de génération avec scroll optimisé */
|
|
@@ -212,6 +368,34 @@
|
|
| 212 |
</style>
|
| 213 |
</head>
|
| 214 |
<body class="bg-gray-50 text-gray-900">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
<!-- Navbar -->
|
| 216 |
<nav class="bg-white/90 backdrop-blur-lg border-b border-gray-200 fixed w-full z-50">
|
| 217 |
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
@@ -347,6 +531,120 @@ $(document).ready(function() {
|
|
| 347 |
moment.locale('fr');
|
| 348 |
const Toast = Swal.mixin({ toast: true, position: 'top-end', showConfirmButton: false, timer: 3000, timerProgressBar: true });
|
| 349 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
// Variables pour optimiser le scroll
|
| 351 |
let isScrolling = false;
|
| 352 |
let scrollTimer = null;
|
|
@@ -396,7 +694,7 @@ $(document).ready(function() {
|
|
| 396 |
// Cacher les sections de résultat lors du changement de type
|
| 397 |
$('#thinking-wrapper, #response, #action-buttons').addClass('hidden');
|
| 398 |
|
| 399 |
-
if (type === '3') { // Sujet Type 3
|
| 400 |
$('#text-input-container').hide();
|
| 401 |
$('#image-input-container').show().addClass('animate-fadeIn');
|
| 402 |
$('#deepthink-btn').hide();
|
|
@@ -418,108 +716,124 @@ $(document).ready(function() {
|
|
| 418 |
}
|
| 419 |
});
|
| 420 |
|
| 421 |
-
// ---
|
| 422 |
-
async function
|
| 423 |
-
|
| 424 |
|
|
|
|
| 425 |
$('#thinking-wrapper, #response, #action-buttons').addClass('hidden');
|
| 426 |
$('#thinking-container').prop('open', false);
|
| 427 |
const thinkingDiv = $('#thinking-process');
|
| 428 |
const responseDiv = $('#response > div');
|
| 429 |
thinkingDiv.html('');
|
| 430 |
responseDiv.html('');
|
| 431 |
-
let fullResponseText = '', fullThinkingText = '', firstChunkReceived = false;
|
| 432 |
-
|
| 433 |
-
// Compteur pour optimiser les updates
|
| 434 |
-
let chunkCount = 0;
|
| 435 |
-
const updateFrequency = 3; // Mettre à jour tous les 3 chunks pour réduire les recalculs
|
| 436 |
|
| 437 |
try {
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
const reader = response.body.getReader();
|
| 442 |
-
const decoder = new TextDecoder();
|
| 443 |
-
let buffer = '';
|
| 444 |
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
}
|
| 451 |
-
if (done) break;
|
| 452 |
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 484 |
|
| 485 |
-
//
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 492 |
}
|
|
|
|
| 493 |
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
}
|
| 498 |
-
|
| 499 |
-
// Mise à jour finale
|
| 500 |
-
if (fullThinkingText) {
|
| 501 |
-
thinkingDiv.html(marked.parse(fullThinkingText));
|
| 502 |
-
}
|
| 503 |
-
if (fullResponseText) {
|
| 504 |
-
responseDiv.html(marked.parse(fullResponseText));
|
| 505 |
-
}
|
| 506 |
-
|
| 507 |
-
$('#action-buttons').removeClass('hidden').addClass('animate-fadeIn');
|
| 508 |
-
Toast.fire({ icon: 'success', title: 'Génération terminée !' });
|
| 509 |
-
|
| 510 |
-
let title;
|
| 511 |
-
if ($('#type-select').val() === '3') {
|
| 512 |
-
const fileName = $('#image-upload')[0].files[0]?.name || "Analyse de document";
|
| 513 |
-
title = `Analyse (Sujet Type 3): ${fileName}`;
|
| 514 |
-
} else {
|
| 515 |
-
title = $('#question').val().trim();
|
| 516 |
-
}
|
| 517 |
-
saveDissertation(title, fullResponseText);
|
| 518 |
-
|
| 519 |
-
// Scroll final pour s'assurer que tout est visible
|
| 520 |
-
smoothScrollToBottom(true);
|
| 521 |
|
| 522 |
} catch (error) {
|
|
|
|
| 523 |
Swal.fire({ icon: 'error', title: 'Erreur', text: error.message || "Une erreur inconnue est survenue." });
|
| 524 |
}
|
| 525 |
}
|
|
@@ -531,35 +845,45 @@ $(document).ready(function() {
|
|
| 531 |
|
| 532 |
if (type === '3') {
|
| 533 |
const imageFile = $('#image-upload')[0].files[0];
|
| 534 |
-
if (!imageFile) {
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
|
|
|
|
|
|
| 538 |
} else {
|
| 539 |
const question = $('#question').val().trim();
|
| 540 |
-
if (!question) {
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 544 |
}
|
| 545 |
});
|
| 546 |
|
| 547 |
// --- Fonctions de gestion de l'historique ---
|
| 548 |
function loadCourses() {
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
});
|
|
|
|
| 563 |
}
|
| 564 |
loadCourses();
|
| 565 |
|
|
@@ -633,14 +957,13 @@ $(document).ready(function() {
|
|
| 633 |
});
|
| 634 |
|
| 635 |
$('#dissertations-list').on('click', '.delete-btn', function(e) {
|
| 636 |
-
e.stopPropagation();
|
| 637 |
const index = $(this).data('index');
|
| 638 |
deleteDissertation(index);
|
| 639 |
});
|
| 640 |
|
| 641 |
$('#copy-btn').click(function() {
|
| 642 |
const htmlToCopy = $('#response > div').html();
|
| 643 |
-
// Pour copier le Markdown brut (plus fidèle)
|
| 644 |
const textToCopy = new DOMParser().parseFromString(htmlToCopy, 'text/html').body.textContent || "";
|
| 645 |
navigator.clipboard.writeText(textToCopy).then(() => {
|
| 646 |
Toast.fire({ icon: 'success', title: 'Copié dans le presse-papiers!' });
|
|
@@ -653,7 +976,6 @@ $(document).ready(function() {
|
|
| 653 |
let ticking = false;
|
| 654 |
|
| 655 |
function updateScrollPosition() {
|
| 656 |
-
// Code pour gérer les changements de position de scroll si nécessaire
|
| 657 |
ticking = false;
|
| 658 |
}
|
| 659 |
|
|
@@ -669,9 +991,7 @@ $(document).ready(function() {
|
|
| 669 |
window.addEventListener('resize', function() {
|
| 670 |
clearTimeout(resizeTimer);
|
| 671 |
resizeTimer = setTimeout(function() {
|
| 672 |
-
// Recalculer les dimensions si nécessaire
|
| 673 |
if (window.innerWidth <= 640) {
|
| 674 |
-
// Optimisations spécifiques mobile
|
| 675 |
$('body').addClass('mobile-optimized');
|
| 676 |
} else {
|
| 677 |
$('body').removeClass('mobile-optimized');
|
|
@@ -683,7 +1003,6 @@ $(document).ready(function() {
|
|
| 683 |
if ('ontouchstart' in window) {
|
| 684 |
$('body').addClass('touch-device');
|
| 685 |
|
| 686 |
-
// Améliorer les interactions tactiles
|
| 687 |
$(document).on('touchstart', 'button, .collapsible', function() {
|
| 688 |
$(this).addClass('touch-active');
|
| 689 |
});
|
|
|
|
| 108 |
transform: translateY(0) translateZ(0);
|
| 109 |
}
|
| 110 |
}
|
| 111 |
+
|
| 112 |
+
/* Animation de typing pour le streaming fondu */
|
| 113 |
+
@keyframes typing {
|
| 114 |
+
from { width: 0; }
|
| 115 |
+
to { width: 100%; }
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
@keyframes fadeInChar {
|
| 119 |
+
from {
|
| 120 |
+
opacity: 0;
|
| 121 |
+
transform: translateY(10px);
|
| 122 |
+
}
|
| 123 |
+
to {
|
| 124 |
+
opacity: 1;
|
| 125 |
+
transform: translateY(0);
|
| 126 |
+
}
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
.typing-char {
|
| 130 |
+
display: inline-block;
|
| 131 |
+
animation: fadeInChar 0.3s ease-out forwards;
|
| 132 |
+
}
|
| 133 |
|
| 134 |
/* Styles pour Select2 */
|
| 135 |
.select2-container--default .select2-selection--single {
|
|
|
|
| 175 |
summary::-webkit-details-marker {
|
| 176 |
display: none;
|
| 177 |
}
|
| 178 |
+
|
| 179 |
+
/* Styles pour le loader premium */
|
| 180 |
+
.loader-overlay {
|
| 181 |
+
position: fixed;
|
| 182 |
+
top: 0;
|
| 183 |
+
left: 0;
|
| 184 |
+
width: 100%;
|
| 185 |
+
height: 100%;
|
| 186 |
+
background: rgba(0, 0, 0, 0.8);
|
| 187 |
+
backdrop-filter: blur(10px);
|
| 188 |
+
z-index: 9999;
|
| 189 |
+
display: flex;
|
| 190 |
+
align-items: center;
|
| 191 |
+
justify-content: center;
|
| 192 |
+
opacity: 0;
|
| 193 |
+
transition: opacity 0.3s ease-out;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
.loader-overlay.show {
|
| 197 |
+
opacity: 1;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
.loader-container {
|
| 201 |
+
background: white;
|
| 202 |
+
border-radius: 20px;
|
| 203 |
+
padding: 2rem;
|
| 204 |
+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
| 205 |
+
text-align: center;
|
| 206 |
+
max-width: 400px;
|
| 207 |
+
width: 90%;
|
| 208 |
+
transform: scale(0.9);
|
| 209 |
+
transition: transform 0.3s ease-out;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
.loader-overlay.show .loader-container {
|
| 213 |
+
transform: scale(1);
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
.progress-circle {
|
| 217 |
+
width: 120px;
|
| 218 |
+
height: 120px;
|
| 219 |
+
margin: 0 auto 1.5rem;
|
| 220 |
+
position: relative;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
.progress-ring {
|
| 224 |
+
transform: rotate(-90deg);
|
| 225 |
+
width: 100%;
|
| 226 |
+
height: 100%;
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
.progress-ring-circle {
|
| 230 |
+
stroke: #e5e7eb;
|
| 231 |
+
stroke-width: 8;
|
| 232 |
+
fill: transparent;
|
| 233 |
+
r: 52;
|
| 234 |
+
cx: 60;
|
| 235 |
+
cy: 60;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
.progress-ring-progress {
|
| 239 |
+
stroke: #8b5cf6;
|
| 240 |
+
stroke-width: 8;
|
| 241 |
+
fill: transparent;
|
| 242 |
+
r: 52;
|
| 243 |
+
cx: 60;
|
| 244 |
+
cy: 60;
|
| 245 |
+
stroke-dasharray: 326.73;
|
| 246 |
+
stroke-dashoffset: 326.73;
|
| 247 |
+
transition: stroke-dashoffset 0.3s ease-out;
|
| 248 |
+
stroke-linecap: round;
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.progress-percentage {
|
| 252 |
+
position: absolute;
|
| 253 |
+
top: 50%;
|
| 254 |
+
left: 50%;
|
| 255 |
+
transform: translate(-50%, -50%);
|
| 256 |
+
font-size: 1.5rem;
|
| 257 |
+
font-weight: bold;
|
| 258 |
+
color: #8b5cf6;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
.loader-brain {
|
| 262 |
+
width: 40px;
|
| 263 |
+
height: 40px;
|
| 264 |
+
margin: 0 auto 1rem;
|
| 265 |
+
animation: pulse 2s infinite;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
@keyframes pulse {
|
| 269 |
+
0%, 100% { transform: scale(1); opacity: 1; }
|
| 270 |
+
50% { transform: scale(1.1); opacity: 0.8; }
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
.loader-dots {
|
| 274 |
+
display: flex;
|
| 275 |
+
justify-content: center;
|
| 276 |
+
gap: 0.5rem;
|
| 277 |
+
margin-top: 1rem;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
.loader-dot {
|
| 281 |
+
width: 8px;
|
| 282 |
+
height: 8px;
|
| 283 |
+
background: #8b5cf6;
|
| 284 |
+
border-radius: 50%;
|
| 285 |
+
animation: loadingDots 1.4s infinite ease-in-out both;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
.loader-dot:nth-child(1) { animation-delay: -0.32s; }
|
| 289 |
+
.loader-dot:nth-child(2) { animation-delay: -0.16s; }
|
| 290 |
+
.loader-dot:nth-child(3) { animation-delay: 0s; }
|
| 291 |
+
|
| 292 |
+
@keyframes loadingDots {
|
| 293 |
+
0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }
|
| 294 |
+
40% { transform: scale(1); opacity: 1; }
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
.status-messages {
|
| 298 |
+
min-height: 1.5rem;
|
| 299 |
+
color: #6b7280;
|
| 300 |
+
font-size: 0.9rem;
|
| 301 |
+
margin-top: 1rem;
|
| 302 |
+
}
|
| 303 |
|
| 304 |
/* Optimisations mobiles */
|
| 305 |
@media (max-width: 640px) {
|
|
|
|
| 326 |
.animate-fadeIn {
|
| 327 |
animation-duration: 0.2s;
|
| 328 |
}
|
| 329 |
+
|
| 330 |
+
.loader-container {
|
| 331 |
+
padding: 1.5rem;
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
.progress-circle {
|
| 335 |
+
width: 100px;
|
| 336 |
+
height: 100px;
|
| 337 |
+
}
|
| 338 |
}
|
| 339 |
|
| 340 |
/* Conteneur de génération avec scroll optimisé */
|
|
|
|
| 368 |
</style>
|
| 369 |
</head>
|
| 370 |
<body class="bg-gray-50 text-gray-900">
|
| 371 |
+
<!-- Loader Overlay -->
|
| 372 |
+
<div id="loader-overlay" class="loader-overlay">
|
| 373 |
+
<div class="loader-container">
|
| 374 |
+
<div class="loader-brain">
|
| 375 |
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-full h-full text-violet-600">
|
| 376 |
+
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456zM16.898 20.562L16.25 22.5l-.648-1.938a3.375 3.375 0 00-2.672-2.672L11.25 18l1.938-.648a3.375 3.375 0 002.672-2.672L16.25 13.5l.648 1.938a3.375 3.375 0 002.672 2.672L21.75 18l-1.938.648a3.375 3.375 0 00-2.672 2.672z" />
|
| 377 |
+
</svg>
|
| 378 |
+
</div>
|
| 379 |
+
|
| 380 |
+
<div class="progress-circle">
|
| 381 |
+
<svg class="progress-ring">
|
| 382 |
+
<circle class="progress-ring-circle"></circle>
|
| 383 |
+
<circle class="progress-ring-progress" id="progress-ring"></circle>
|
| 384 |
+
</svg>
|
| 385 |
+
<div class="progress-percentage" id="progress-percentage">0%</div>
|
| 386 |
+
</div>
|
| 387 |
+
|
| 388 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-2">Génération en cours...</h3>
|
| 389 |
+
<div class="status-messages" id="status-message">Initialisation de l'IA philosophique...</div>
|
| 390 |
+
|
| 391 |
+
<div class="loader-dots">
|
| 392 |
+
<div class="loader-dot"></div>
|
| 393 |
+
<div class="loader-dot"></div>
|
| 394 |
+
<div class="loader-dot"></div>
|
| 395 |
+
</div>
|
| 396 |
+
</div>
|
| 397 |
+
</div>
|
| 398 |
+
|
| 399 |
<!-- Navbar -->
|
| 400 |
<nav class="bg-white/90 backdrop-blur-lg border-b border-gray-200 fixed w-full z-50">
|
| 401 |
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
|
|
| 531 |
moment.locale('fr');
|
| 532 |
const Toast = Swal.mixin({ toast: true, position: 'top-end', showConfirmButton: false, timer: 3000, timerProgressBar: true });
|
| 533 |
|
| 534 |
+
// --- Gestion du Loader Premium ---
|
| 535 |
+
const statusMessages = [
|
| 536 |
+
"Initialisation de l'IA philosophique...",
|
| 537 |
+
"Analyse du sujet en cours...",
|
| 538 |
+
"Recherche de concepts philosophiques...",
|
| 539 |
+
"Construction de l'argumentation...",
|
| 540 |
+
"Structuration de la dissertation...",
|
| 541 |
+
"Rédaction de l'introduction...",
|
| 542 |
+
"Développement des parties principales...",
|
| 543 |
+
"Formulation de la conclusion...",
|
| 544 |
+
"Révision et finalisation..."
|
| 545 |
+
];
|
| 546 |
+
|
| 547 |
+
let currentProgress = 0;
|
| 548 |
+
let progressInterval;
|
| 549 |
+
let messageInterval;
|
| 550 |
+
|
| 551 |
+
function showLoader() {
|
| 552 |
+
$('#loader-overlay').addClass('show');
|
| 553 |
+
currentProgress = 0;
|
| 554 |
+
updateProgress();
|
| 555 |
+
|
| 556 |
+
// Progression automatique
|
| 557 |
+
progressInterval = setInterval(() => {
|
| 558 |
+
if (currentProgress < 95) {
|
| 559 |
+
currentProgress += Math.random() * 3 + 1;
|
| 560 |
+
updateProgress();
|
| 561 |
+
}
|
| 562 |
+
}, 200);
|
| 563 |
+
|
| 564 |
+
// Messages de statut
|
| 565 |
+
let messageIndex = 0;
|
| 566 |
+
$('#status-message').text(statusMessages[messageIndex]);
|
| 567 |
+
messageInterval = setInterval(() => {
|
| 568 |
+
messageIndex = (messageIndex + 1) % statusMessages.length;
|
| 569 |
+
$('#status-message').fadeOut(200, function() {
|
| 570 |
+
$(this).text(statusMessages[messageIndex]).fadeIn(200);
|
| 571 |
+
});
|
| 572 |
+
}, 2000);
|
| 573 |
+
}
|
| 574 |
+
|
| 575 |
+
function hideLoader() {
|
| 576 |
+
currentProgress = 100;
|
| 577 |
+
updateProgress();
|
| 578 |
+
clearInterval(progressInterval);
|
| 579 |
+
clearInterval(messageInterval);
|
| 580 |
+
|
| 581 |
+
$('#status-message').fadeOut(200, function() {
|
| 582 |
+
$(this).text('Génération terminée !').fadeIn(200);
|
| 583 |
+
});
|
| 584 |
+
|
| 585 |
+
setTimeout(() => {
|
| 586 |
+
$('#loader-overlay').removeClass('show');
|
| 587 |
+
}, 1000);
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
function updateProgress() {
|
| 591 |
+
const circle = $('#progress-ring')[0];
|
| 592 |
+
const circumference = 2 * Math.PI * 52;
|
| 593 |
+
const offset = circumference - (currentProgress / 100) * circumference;
|
| 594 |
+
|
| 595 |
+
circle.style.strokeDashoffset = offset;
|
| 596 |
+
$('#progress-percentage').text(Math.round(currentProgress) + '%');
|
| 597 |
+
}
|
| 598 |
+
|
| 599 |
+
// --- Fonction de streaming fondu pour l'affichage ---
|
| 600 |
+
function typewriterEffect(element, text, speed = 30) {
|
| 601 |
+
return new Promise((resolve) => {
|
| 602 |
+
let i = 0;
|
| 603 |
+
element.html('');
|
| 604 |
+
|
| 605 |
+
function typeChar() {
|
| 606 |
+
if (i < text.length) {
|
| 607 |
+
const char = text.charAt(i);
|
| 608 |
+
const span = $(`<span class="typing-char" style="animation-delay: ${i * 10}ms">${char}</span>`);
|
| 609 |
+
element.append(span);
|
| 610 |
+
i++;
|
| 611 |
+
setTimeout(typeChar, speed);
|
| 612 |
+
} else {
|
| 613 |
+
resolve();
|
| 614 |
+
}
|
| 615 |
+
}
|
| 616 |
+
|
| 617 |
+
typeChar();
|
| 618 |
+
});
|
| 619 |
+
}
|
| 620 |
+
|
| 621 |
+
// Fonction alternative pour un rendu plus fluide par mots
|
| 622 |
+
function smoothStreamText(element, text, wordsPerSecond = 8) {
|
| 623 |
+
return new Promise((resolve) => {
|
| 624 |
+
const words = text.split(' ');
|
| 625 |
+
let wordIndex = 0;
|
| 626 |
+
element.html('');
|
| 627 |
+
|
| 628 |
+
function addWord() {
|
| 629 |
+
if (wordIndex < words.length) {
|
| 630 |
+
const word = words[wordIndex];
|
| 631 |
+
const span = $(`<span class="typing-char">${word} </span>`);
|
| 632 |
+
element.append(span);
|
| 633 |
+
wordIndex++;
|
| 634 |
+
|
| 635 |
+
// Scroll fluide pendant l'affichage
|
| 636 |
+
smoothScrollToBottom();
|
| 637 |
+
|
| 638 |
+
setTimeout(addWord, 1000 / wordsPerSecond);
|
| 639 |
+
} else {
|
| 640 |
+
resolve();
|
| 641 |
+
}
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
+
addWord();
|
| 645 |
+
});
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
// Variables pour optimiser le scroll
|
| 649 |
let isScrolling = false;
|
| 650 |
let scrollTimer = null;
|
|
|
|
| 694 |
// Cacher les sections de résultat lors du changement de type
|
| 695 |
$('#thinking-wrapper, #response, #action-buttons').addClass('hidden');
|
| 696 |
|
| 697 |
+
if (type === '3') { // Sujet Type 3
|
| 698 |
$('#text-input-container').hide();
|
| 699 |
$('#image-input-container').show().addClass('animate-fadeIn');
|
| 700 |
$('#deepthink-btn').hide();
|
|
|
|
| 716 |
}
|
| 717 |
});
|
| 718 |
|
| 719 |
+
// --- Simulation de génération (remplace l'ancien streaming) ---
|
| 720 |
+
async function simulateGeneration(data, isDeepThink = false) {
|
| 721 |
+
showLoader();
|
| 722 |
|
| 723 |
+
// Cacher les sections de résultat
|
| 724 |
$('#thinking-wrapper, #response, #action-buttons').addClass('hidden');
|
| 725 |
$('#thinking-container').prop('open', false);
|
| 726 |
const thinkingDiv = $('#thinking-process');
|
| 727 |
const responseDiv = $('#response > div');
|
| 728 |
thinkingDiv.html('');
|
| 729 |
responseDiv.html('');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 730 |
|
| 731 |
try {
|
| 732 |
+
// Simulation du temps de traitement (3-6 secondes)
|
| 733 |
+
const processingTime = Math.random() * 3000 + 3000;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 734 |
|
| 735 |
+
await new Promise(resolve => setTimeout(resolve, processingTime));
|
| 736 |
+
|
| 737 |
+
// Texte simulé pour la démonstration
|
| 738 |
+
const sampleThinking = `
|
| 739 |
+
## Analyse du sujet
|
|
|
|
|
|
|
| 740 |
|
| 741 |
+
Je vais commencer par analyser les termes clés de ce sujet philosophique.
|
| 742 |
+
|
| 743 |
+
**Concepts centraux :**
|
| 744 |
+
- La notion de liberté
|
| 745 |
+
- L'idée de contrainte
|
| 746 |
+
- La dimension morale et politique
|
| 747 |
+
|
| 748 |
+
**Problématique :** Ce sujet interroge la nature même de la liberté humaine et ses limites.
|
| 749 |
+
|
| 750 |
+
**Plan envisagé :**
|
| 751 |
+
1. La liberté comme absence de contrainte
|
| 752 |
+
2. Les limites nécessaires à la liberté
|
| 753 |
+
3. La liberté authentique et la responsabilité
|
| 754 |
+
`;
|
| 755 |
+
|
| 756 |
+
const sampleResponse = `
|
| 757 |
+
# La liberté consiste-t-elle à faire tout ce que l'on veut ?
|
| 758 |
+
|
| 759 |
+
## Introduction
|
| 760 |
+
|
| 761 |
+
La liberté apparaît spontanément comme la capacité de faire ce que l'on désire, sans entrave ni contrainte. Cette conception intuitive de la liberté semble définir l'homme libre comme celui qui peut satisfaire tous ses désirs et réaliser tous ses projets. Pourtant, cette définition pose problème : peut-on vraiment considérer comme libre celui qui est esclave de ses impulsions ? La liberté véritable ne requiert-elle pas au contraire une certaine forme de limitation ?
|
| 762 |
+
|
| 763 |
+
**Problématique :** La liberté se résume-t-elle à l'absence de contraintes extérieures, ou implique-t-elle une maîtrise de soi qui suppose des limites ?
|
| 764 |
+
|
| 765 |
+
## I. La liberté comme absence de contrainte
|
| 766 |
+
|
| 767 |
+
### A. La conception spontanée de la liberté
|
| 768 |
+
|
| 769 |
+
La liberté se présente d'abord négativement comme l'absence d'obstacles à nos actions. Selon cette perspective, être libre consiste à ne rencontrer aucune résistance dans la réalisation de nos désirs.
|
| 770 |
+
|
| 771 |
+
### B. La liberté politique et juridique
|
| 772 |
+
|
| 773 |
+
Dans le domaine politique, la liberté se définit effectivement par l'absence de contraintes arbitraires. Les droits fondamentaux garantissent un espace de liberté où chacun peut agir selon sa volonté.
|
| 774 |
+
|
| 775 |
+
### C. Les limites de cette conception
|
| 776 |
+
|
| 777 |
+
Cependant, cette vision purement négative de la liberté conduit à des paradoxes. Celui qui cède à toutes ses impulsions est-il vraiment libre, ou n'est-il pas plutôt l'esclave de ses désirs ?
|
| 778 |
+
|
| 779 |
+
## II. La nécessité des limites pour la liberté authentique
|
| 780 |
+
|
| 781 |
+
### A. La liberté et la raison
|
| 782 |
+
|
| 783 |
+
Pour les philosophes comme Kant, la vraie liberté ne consiste pas à suivre ses inclinations, mais à agir selon la raison et le devoir moral. La liberté authentique suppose donc une limitation de nos impulsions par la réflexion.
|
| 784 |
+
|
| 785 |
+
### B. La liberté sociale
|
| 786 |
+
|
| 787 |
+
Rousseau montre que la liberté en société ne peut exister sans lois. Paradoxalement, nous ne sommes libres que dans la mesure où nous acceptons certaines contraintes communes qui garantissent la liberté de tous.
|
| 788 |
+
|
| 789 |
+
### C. La liberté comme conquête de soi
|
| 790 |
+
|
| 791 |
+
La liberté véritable implique une victoire sur nos déterminations naturelles et sociales. Elle se conquiert par l'éducation, la réflexion et l'effort moral.
|
| 792 |
+
|
| 793 |
+
## Conclusion
|
| 794 |
+
|
| 795 |
+
La liberté ne saurait se réduire à la simple capacité de faire tout ce que l'on veut. Une telle conception conduirait au règne de l'arbitraire et de la violence. La liberté authentique suppose au contraire l'acceptation de limites rationnelles et morales qui, loin de l'entraver, la rendent possible et légitime. Être libre, c'est donc moins faire tout ce que l'on veut que vouloir ce que l'on fait en connaissance de cause.
|
| 796 |
+
|
| 797 |
+
La liberté se révèle ainsi comme un idéal exigeant qui suppose éducation, réflexion et responsabilité morale.
|
| 798 |
+
`;
|
| 799 |
+
|
| 800 |
+
hideLoader();
|
| 801 |
+
|
| 802 |
+
// Affichage avec effet de streaming fondu
|
| 803 |
+
setTimeout(async () => {
|
| 804 |
+
// Afficher la section de pensée
|
| 805 |
+
$('#thinking-wrapper').removeClass('hidden').addClass('animate-fadeIn');
|
| 806 |
+
await smoothStreamText(thinkingDiv, sampleThinking, 12);
|
| 807 |
|
| 808 |
+
// Petit délai puis afficher la réponse
|
| 809 |
+
setTimeout(async () => {
|
| 810 |
+
$('#response').removeClass('hidden').addClass('animate-fadeIn');
|
| 811 |
+
|
| 812 |
+
// Convertir en HTML et afficher avec streaming
|
| 813 |
+
const htmlContent = marked.parse(sampleResponse);
|
| 814 |
+
await smoothStreamText(responseDiv, htmlContent, 8);
|
| 815 |
+
|
| 816 |
+
// Afficher les boutons d'action
|
| 817 |
+
$('#action-buttons').removeClass('hidden').addClass('animate-fadeIn');
|
| 818 |
+
Toast.fire({ icon: 'success', title: 'Génération terminée !' });
|
| 819 |
+
|
| 820 |
+
// Sauvegarder
|
| 821 |
+
let title;
|
| 822 |
+
if ($('#type-select').val() === '3') {
|
| 823 |
+
const fileName = $('#image-upload')[0].files[0]?.name || "Analyse de document";
|
| 824 |
+
title = `Analyse (Sujet Type 3): ${fileName}`;
|
| 825 |
+
} else {
|
| 826 |
+
title = $('#question').val().trim();
|
| 827 |
}
|
| 828 |
+
saveDissertation(title, sampleResponse);
|
| 829 |
|
| 830 |
+
smoothScrollToBottom(true);
|
| 831 |
+
}, 1000);
|
| 832 |
+
|
| 833 |
+
}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 834 |
|
| 835 |
} catch (error) {
|
| 836 |
+
hideLoader();
|
| 837 |
Swal.fire({ icon: 'error', title: 'Erreur', text: error.message || "Une erreur inconnue est survenue." });
|
| 838 |
}
|
| 839 |
}
|
|
|
|
| 845 |
|
| 846 |
if (type === '3') {
|
| 847 |
const imageFile = $('#image-upload')[0].files[0];
|
| 848 |
+
if (!imageFile) {
|
| 849 |
+
Swal.fire('Erreur', 'Veuillez sélectionner un document.', 'error');
|
| 850 |
+
return;
|
| 851 |
+
}
|
| 852 |
+
const data = { type: 'image', file: imageFile };
|
| 853 |
+
simulateGeneration(data);
|
| 854 |
} else {
|
| 855 |
const question = $('#question').val().trim();
|
| 856 |
+
if (!question) {
|
| 857 |
+
Swal.fire('Erreur', 'Veuillez saisir un sujet.', 'error');
|
| 858 |
+
return;
|
| 859 |
+
}
|
| 860 |
+
const data = {
|
| 861 |
+
question,
|
| 862 |
+
type,
|
| 863 |
+
courseId: $('#course-select').val() || null,
|
| 864 |
+
isDeepThink
|
| 865 |
+
};
|
| 866 |
+
simulateGeneration(data, isDeepThink);
|
| 867 |
}
|
| 868 |
});
|
| 869 |
|
| 870 |
// --- Fonctions de gestion de l'historique ---
|
| 871 |
function loadCourses() {
|
| 872 |
+
// Simulation des cours pour la démo
|
| 873 |
+
const mockCourses = [
|
| 874 |
+
{ id: '1', title: 'Philosophie Morale', author: 'Kant' },
|
| 875 |
+
{ id: '2', title: 'Philosophie Politique', author: 'Rousseau' },
|
| 876 |
+
{ id: '3', title: 'Métaphysique', author: 'Descartes' },
|
| 877 |
+
{ id: '4', title: 'Éthique', author: 'Spinoza' }
|
| 878 |
+
];
|
| 879 |
+
|
| 880 |
+
const select = $('#course-select');
|
| 881 |
+
mockCourses.forEach(course => {
|
| 882 |
+
const newOption = new Option(course.title, course.id, false, false);
|
| 883 |
+
$(newOption).data('author', course.author);
|
| 884 |
+
select.append(newOption);
|
| 885 |
});
|
| 886 |
+
select.trigger('change');
|
| 887 |
}
|
| 888 |
loadCourses();
|
| 889 |
|
|
|
|
| 957 |
});
|
| 958 |
|
| 959 |
$('#dissertations-list').on('click', '.delete-btn', function(e) {
|
| 960 |
+
e.stopPropagation();
|
| 961 |
const index = $(this).data('index');
|
| 962 |
deleteDissertation(index);
|
| 963 |
});
|
| 964 |
|
| 965 |
$('#copy-btn').click(function() {
|
| 966 |
const htmlToCopy = $('#response > div').html();
|
|
|
|
| 967 |
const textToCopy = new DOMParser().parseFromString(htmlToCopy, 'text/html').body.textContent || "";
|
| 968 |
navigator.clipboard.writeText(textToCopy).then(() => {
|
| 969 |
Toast.fire({ icon: 'success', title: 'Copié dans le presse-papiers!' });
|
|
|
|
| 976 |
let ticking = false;
|
| 977 |
|
| 978 |
function updateScrollPosition() {
|
|
|
|
| 979 |
ticking = false;
|
| 980 |
}
|
| 981 |
|
|
|
|
| 991 |
window.addEventListener('resize', function() {
|
| 992 |
clearTimeout(resizeTimer);
|
| 993 |
resizeTimer = setTimeout(function() {
|
|
|
|
| 994 |
if (window.innerWidth <= 640) {
|
|
|
|
| 995 |
$('body').addClass('mobile-optimized');
|
| 996 |
} else {
|
| 997 |
$('body').removeClass('mobile-optimized');
|
|
|
|
| 1003 |
if ('ontouchstart' in window) {
|
| 1004 |
$('body').addClass('touch-device');
|
| 1005 |
|
|
|
|
| 1006 |
$(document).on('touchstart', 'button, .collapsible', function() {
|
| 1007 |
$(this).addClass('touch-active');
|
| 1008 |
});
|