Docfile commited on
Commit
3693d77
·
verified ·
1 Parent(s): a531b8b

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +53 -22
templates/index.html CHANGED
@@ -22,6 +22,10 @@
22
  #historyList::-webkit-scrollbar-track { background: #e0e7ff; }
23
  #historyList::-webkit-scrollbar-thumb { background: #a5b4fc; border-radius: 3px; }
24
  #historyList::-webkit-scrollbar-thumb:hover { background: #818cf8; }
 
 
 
 
25
  </style>
26
  </head>
27
  <body class="min-h-screen text-slate-800">
@@ -29,7 +33,7 @@
29
  <!-- Header -->
30
  <header class="text-center mb-10 md:mb-12 fade-in-up">
31
  <h1 class="text-4xl sm:text-5xl md:text-6xl font-extrabold text-slate-900 mb-3">Synthétiseur AI Pro</h1>
32
- <p class="text-base sm:text-lg text-slate-600 max-w-2xl mx-auto">Transformez vos documents en résumés clairs et concis.</p>
33
  </header>
34
 
35
  <!-- Main Content -->
@@ -40,8 +44,8 @@
40
  <div class="bg-white/80 backdrop-blur-sm border border-slate-200 rounded-2xl shadow-lg p-6 md:p-8 fade-in-up" style="animation-delay: 100ms;">
41
  <form id="uploadForm" class="space-y-6">
42
  <div>
43
- <h2 class="text-xl md:text-2xl font-bold text-slate-800 mb-1">1. Importez votre document</h2>
44
- <p class="text-slate-500 mb-6">Faites glisser ou sélectionnez un fichier.</p>
45
 
46
  <label for="fileInput" id="dropzone" class="group block border-2 border-dashed border-slate-300 rounded-xl p-8 text-center transition-all duration-300 hover:border-blue-500 hover:bg-blue-50 cursor-pointer">
47
  <input type="file" id="fileInput" name="file" class="hidden" accept=".pdf,.mp3,.mp4,.wav,.txt,.doc,.docx">
@@ -51,6 +55,13 @@
51
  <p class="text-xs sm:text-sm">PDF, MP3, MP4, WAV, TXT, DOCX (Max 50MB)</p>
52
  </div>
53
  </label>
 
 
 
 
 
 
 
54
  </div>
55
 
56
  <div id="fileInfo" class="hidden items-center justify-between bg-slate-100 rounded-lg p-3">
@@ -143,17 +154,12 @@
143
  const { jsPDF } = window.jspdf;
144
 
145
  // DOM Elements
146
- const fileIconContainer = document.getElementById('fileIconContainer');
147
- const summaryContent = document.getElementById('summaryContent');
148
- const summaryContentWrapper = document.getElementById('summaryContentWrapper');
149
- const downloadBtn = document.getElementById('downloadBtn');
150
- const downloadBtnText = document.getElementById('downloadBtnText');
151
- const downloadBtnIcon = document.getElementById('downloadBtnIcon');
152
- const downloadBtnSpinner = document.getElementById('downloadBtnSpinner');
153
  const uploadForm = document.getElementById('uploadForm');
154
  const fileInput = document.getElementById('fileInput');
 
155
  const dropzone = document.getElementById('dropzone');
156
  const fileInfo = document.getElementById('fileInfo');
 
157
  const fileNameText = document.getElementById('fileNameText');
158
  const fileSizeText = document.getElementById('fileSizeText');
159
  const removeFileBtn = document.getElementById('removeFileBtn');
@@ -161,17 +167,22 @@
161
  const btnText = document.getElementById('btnText');
162
  const btnSpinner = document.getElementById('btnSpinner');
163
  const resultCard = document.getElementById('resultCard');
164
- const errorCard = document.getElementById('errorCard');
165
  const resultFilename = document.getElementById('resultFilename');
 
 
 
166
  const errorMessage = document.getElementById('errorMessage');
167
  const copyBtn = document.getElementById('copyBtn');
168
  const copyBtnText = document.getElementById('copyBtnText');
 
 
 
 
169
  const historyList = document.getElementById('historyList');
170
  const historyEmptyState = document.getElementById('historyEmptyState');
171
  const clearHistoryBtn = document.getElementById('clearHistory');
172
 
173
  let currentHistoryId = null;
174
- let originalFile = null;
175
 
176
  // --- UI Helper Functions ---
177
  function showLoading(isLoading) {
@@ -192,6 +203,9 @@
192
  }
193
 
194
  function getFileIcon(filename, sizeClass = 'w-6 h-6') {
 
 
 
195
  const extension = filename.split('.').pop().toLowerCase();
196
  let iconSvg = '';
197
  switch (extension) {
@@ -202,11 +216,17 @@
202
  }
203
  return iconSvg;
204
  }
 
 
 
 
 
 
205
 
206
  // --- Event Listeners & Core Logic ---
207
  function handleFileSelect(file) {
208
  if (!file) return;
209
- originalFile = file;
210
  fileNameText.textContent = file.name;
211
  fileSizeText.textContent = `${(file.size / 1024 / 1024).toFixed(2)} MB`;
212
  fileIconContainer.innerHTML = getFileIcon(file.name);
@@ -225,25 +245,36 @@
225
  fileInput.files = e.dataTransfer.files;
226
  handleFileSelect(file);
227
  });
228
- removeFileBtn.addEventListener('click', () => {
229
- originalFile = null; fileInput.value = '';
230
- fileInfo.classList.add('hidden'); fileInfo.classList.remove('flex');
231
- dropzone.classList.remove('hidden');
 
 
232
  });
233
 
234
  uploadForm.addEventListener('submit', async (e) => {
235
  e.preventDefault();
236
- if (!fileInput.files[0]) { alert('Veuillez sélectionner un fichier.'); return; }
 
 
 
237
  showLoading(true);
238
- resultCard.classList.add('hidden'); errorCard.classList.add('hidden');
 
 
239
  const formData = new FormData(uploadForm);
 
240
  try {
241
  const response = await fetch('/upload', { method: 'POST', body: formData });
242
  const data = await response.json();
243
  if (!response.ok || data.error) throw new Error(data.error || `Erreur serveur: ${response.status}`);
244
- const newItem = { id: data.history_id, summary: data.summary, filename: originalFile.name };
 
 
245
  displaySummary(newItem);
246
  loadHistory();
 
247
  } catch (err) {
248
  errorMessage.textContent = err.message;
249
  errorCard.classList.remove('hidden'); errorCard.classList.add('fade-in-up');
@@ -284,7 +315,7 @@
284
  heightLeft -= pdfHeight;
285
  }
286
 
287
- const safeFilename = resultFilename.textContent.replace(/\.[^/.]+$/, "") + "_resume.pdf";
288
  pdf.save(safeFilename);
289
 
290
  } catch (err) {
@@ -294,7 +325,7 @@
294
  downloadBtn.disabled = false;
295
  downloadBtnText.textContent = 'Télécharger PDF';
296
  downloadBtnIcon.classList.remove('hidden');
297
- downloadBtnSpinner.classList.add('hidden');
298
  }
299
  });
300
 
 
22
  #historyList::-webkit-scrollbar-track { background: #e0e7ff; }
23
  #historyList::-webkit-scrollbar-thumb { background: #a5b4fc; border-radius: 3px; }
24
  #historyList::-webkit-scrollbar-thumb:hover { background: #818cf8; }
25
+ .divider { display: flex; align-items: center; text-align: center; margin: 1.25rem 0; color: #94a3b8; }
26
+ .divider::before, .divider::after { content: ''; flex: 1; border-bottom: 1px solid #e2e8f0; }
27
+ .divider:not(:empty)::before { margin-right: .75em; }
28
+ .divider:not(:empty)::after { margin-left: .75em; }
29
  </style>
30
  </head>
31
  <body class="min-h-screen text-slate-800">
 
33
  <!-- Header -->
34
  <header class="text-center mb-10 md:mb-12 fade-in-up">
35
  <h1 class="text-4xl sm:text-5xl md:text-6xl font-extrabold text-slate-900 mb-3">Synthétiseur AI Pro</h1>
36
+ <p class="text-base sm:text-lg text-slate-600 max-w-2xl mx-auto">Transformez vos documents et vidéos en résumés clairs et concis.</p>
37
  </header>
38
 
39
  <!-- Main Content -->
 
44
  <div class="bg-white/80 backdrop-blur-sm border border-slate-200 rounded-2xl shadow-lg p-6 md:p-8 fade-in-up" style="animation-delay: 100ms;">
45
  <form id="uploadForm" class="space-y-6">
46
  <div>
47
+ <h2 class="text-xl md:text-2xl font-bold text-slate-800 mb-1">1. Choisissez votre source</h2>
48
+ <p class="text-slate-500 mb-6">Importez un fichier ou collez un lien YouTube.</p>
49
 
50
  <label for="fileInput" id="dropzone" class="group block border-2 border-dashed border-slate-300 rounded-xl p-8 text-center transition-all duration-300 hover:border-blue-500 hover:bg-blue-50 cursor-pointer">
51
  <input type="file" id="fileInput" name="file" class="hidden" accept=".pdf,.mp3,.mp4,.wav,.txt,.doc,.docx">
 
55
  <p class="text-xs sm:text-sm">PDF, MP3, MP4, WAV, TXT, DOCX (Max 50MB)</p>
56
  </div>
57
  </label>
58
+
59
+ <div class="divider">OU</div>
60
+
61
+ <div>
62
+ <label for="youtubeUrlInput" class="block text-sm font-medium text-slate-700 mb-2">Pour une vidéo YouTube</label>
63
+ <input type="url" id="youtubeUrlInput" name="youtube_url" class="block w-full px-4 py-2.5 text-slate-800 bg-slate-50 border border-slate-300 rounded-lg focus:ring-blue-500 focus:border-blue-500 transition-colors" placeholder="https://www.youtube.com/watch?v=...">
64
+ </div>
65
  </div>
66
 
67
  <div id="fileInfo" class="hidden items-center justify-between bg-slate-100 rounded-lg p-3">
 
154
  const { jsPDF } = window.jspdf;
155
 
156
  // DOM Elements
 
 
 
 
 
 
 
157
  const uploadForm = document.getElementById('uploadForm');
158
  const fileInput = document.getElementById('fileInput');
159
+ const youtubeUrlInput = document.getElementById('youtubeUrlInput');
160
  const dropzone = document.getElementById('dropzone');
161
  const fileInfo = document.getElementById('fileInfo');
162
+ const fileIconContainer = document.getElementById('fileIconContainer');
163
  const fileNameText = document.getElementById('fileNameText');
164
  const fileSizeText = document.getElementById('fileSizeText');
165
  const removeFileBtn = document.getElementById('removeFileBtn');
 
167
  const btnText = document.getElementById('btnText');
168
  const btnSpinner = document.getElementById('btnSpinner');
169
  const resultCard = document.getElementById('resultCard');
 
170
  const resultFilename = document.getElementById('resultFilename');
171
+ const summaryContent = document.getElementById('summaryContent');
172
+ const summaryContentWrapper = document.getElementById('summaryContentWrapper');
173
+ const errorCard = document.getElementById('errorCard');
174
  const errorMessage = document.getElementById('errorMessage');
175
  const copyBtn = document.getElementById('copyBtn');
176
  const copyBtnText = document.getElementById('copyBtnText');
177
+ const downloadBtn = document.getElementById('downloadBtn');
178
+ const downloadBtnText = document.getElementById('downloadBtnText');
179
+ const downloadBtnIcon = document.getElementById('downloadBtnIcon');
180
+ const downloadBtnSpinner = document.getElementById('downloadBtnSpinner');
181
  const historyList = document.getElementById('historyList');
182
  const historyEmptyState = document.getElementById('historyEmptyState');
183
  const clearHistoryBtn = document.getElementById('clearHistory');
184
 
185
  let currentHistoryId = null;
 
186
 
187
  // --- UI Helper Functions ---
188
  function showLoading(isLoading) {
 
203
  }
204
 
205
  function getFileIcon(filename, sizeClass = 'w-6 h-6') {
206
+ if (filename === 'Vidéo YouTube') {
207
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="${sizeClass} text-red-600"><path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"></path></svg>`;
208
+ }
209
  const extension = filename.split('.').pop().toLowerCase();
210
  let iconSvg = '';
211
  switch (extension) {
 
216
  }
217
  return iconSvg;
218
  }
219
+
220
+ function resetFileSelection() {
221
+ fileInput.value = '';
222
+ fileInfo.classList.add('hidden'); fileInfo.classList.remove('flex');
223
+ dropzone.classList.remove('hidden');
224
+ }
225
 
226
  // --- Event Listeners & Core Logic ---
227
  function handleFileSelect(file) {
228
  if (!file) return;
229
+ youtubeUrlInput.value = ''; // Clear URL input if a file is selected
230
  fileNameText.textContent = file.name;
231
  fileSizeText.textContent = `${(file.size / 1024 / 1024).toFixed(2)} MB`;
232
  fileIconContainer.innerHTML = getFileIcon(file.name);
 
245
  fileInput.files = e.dataTransfer.files;
246
  handleFileSelect(file);
247
  });
248
+ removeFileBtn.addEventListener('click', resetFileSelection);
249
+
250
+ youtubeUrlInput.addEventListener('input', () => {
251
+ if (youtubeUrlInput.value.trim() !== '') {
252
+ resetFileSelection(); // Clear file selection if URL is being typed
253
+ }
254
  });
255
 
256
  uploadForm.addEventListener('submit', async (e) => {
257
  e.preventDefault();
258
+ if (!fileInput.files[0] && !youtubeUrlInput.value.trim()) {
259
+ alert('Veuillez sélectionner un fichier ou entrer une URL YouTube.');
260
+ return;
261
+ }
262
  showLoading(true);
263
+ resultCard.classList.add('hidden');
264
+ errorCard.classList.add('hidden');
265
+
266
  const formData = new FormData(uploadForm);
267
+
268
  try {
269
  const response = await fetch('/upload', { method: 'POST', body: formData });
270
  const data = await response.json();
271
  if (!response.ok || data.error) throw new Error(data.error || `Erreur serveur: ${response.status}`);
272
+
273
+ let sourceName = fileInput.files[0] ? fileInput.files[0].name : 'Vidéo YouTube';
274
+ const newItem = { id: data.history_id, summary: data.summary, filename: sourceName };
275
  displaySummary(newItem);
276
  loadHistory();
277
+
278
  } catch (err) {
279
  errorMessage.textContent = err.message;
280
  errorCard.classList.remove('hidden'); errorCard.classList.add('fade-in-up');
 
315
  heightLeft -= pdfHeight;
316
  }
317
 
318
+ const safeFilename = resultFilename.textContent.replace(/[^a-z0-9]/gi, '_').toLowerCase() + "_resume.pdf";
319
  pdf.save(safeFilename);
320
 
321
  } catch (err) {
 
325
  downloadBtn.disabled = false;
326
  downloadBtnText.textContent = 'Télécharger PDF';
327
  downloadBtnIcon.classList.remove('hidden');
328
+ downloadBtnSpinner.add('hidden');
329
  }
330
  });
331