Docfile's picture
Update templates/index.html
2eeed13 verified
raw
history blame
14.7 kB
<!DOCTYPE html>
<html lang="fr">
<!-- [Head section reste identique jusqu'aux styles] -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mariam Espagnol - Analyse de Documents</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/[email protected]/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.24.1/prism.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.24.1/themes/prism.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Poppins:wght@300;400;500;600&display=swap');
.fade-in {
animation: fadeIn 0.5s ease-in;
}
.slide-up {
animation: slideUp 0.5s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.gradient-text {
background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.upload-zone {
background: linear-gradient(145deg, #ffffff, #f3f4f6);
box-shadow: 20px 20px 60px #d1d1d1,
-20px -20px 60px #ffffff;
}
.upload-zone:hover {
transform: scale(1.01);
transition: all 0.3s ease;
}
.waves {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
overflow: hidden;
line-height: 0;
transform: rotate(180deg);
}
.waves svg {
position: relative;
display: block;
width: calc(100% + 1.3px);
height: 150px;
}
.prose {
max-width: none;
color: #374151;
}
.prose h1, .prose h2, .prose h3 {
color: #1F2937;
font-family: 'Playfair Display', serif;
margin-top: 2em;
margin-bottom: 1em;
}
.prose p {
margin-bottom: 1.5em;
line-height: 1.8;
}
/* [Styles précédents restent identiques] */
.button-submit {
background: linear-gradient(45deg, #4F46E5, #818CF8);
transition: all 0.3s ease;
}
.button-submit:hover {
transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(79, 70, 229, 0.2);
}
.option-card {
transition: all 0.3s ease;
}
.option-card:hover {
transform: translateY(-5px);
}
.file-input {
display: none;
}
</style>
</head>
<body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen relative">
<!-- [Waves section reste identique] -->
<div class="waves">
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="fill-indigo-50"></path>
</svg>
</div>
<div class="max-w-6xl mx-auto px-4 py-12 relative z-10">
<!-- Header -->
<header class="text-center mb-16 fade-in">
<h1 class="text-5xl md:text-6xl font-bold mb-4 font-['Playfair_Display'] gradient-text">
Mariam Espagnol
</h1>
<p class="text-xl text-gray-600 font-light max-w-2xl mx-auto">
Analysez vos documents en espagnol avec une traduction française précise et élégante
</p>
</header>
<!-- Main Content -->
<div class="bg-white rounded-2xl shadow-xl p-6 md:p-8 mb-8 slide-up">
<!-- Document Type Selection -->
<div class="mb-8 grid md:grid-cols-2 gap-6">
<div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
onclick="selectDocType('iconographic')">
<input type="radio" name="docType" value="iconographic" class="sr-only" checked>
<div class="flex items-center mb-4">
<svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
<h3 class="ml-3 text-lg font-semibold">Document Iconographique</h3>
</div>
<p class="text-gray-600 text-sm">Images, photos, illustrations, publicités, etc.</p>
</div>
<div class="option-card p-6 rounded-xl border-2 border-gray-200 hover:border-indigo-500 cursor-pointer transition-all"
onclick="selectDocType('textual')">
<input type="radio" name="docType" value="textual" class="sr-only">
<div class="flex items-center mb-4">
<svg class="w-8 h-8 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
<h3 class="ml-3 text-lg font-semibold">Document Textuel</h3>
</div>
<p class="text-gray-600 text-sm">Textes, articles, documents écrits, etc.</p>
</div>
</div>
<!-- File Selection -->
<div class="mb-8">
<button onclick="openFileSelection()" class="w-full py-4 px-6 rounded-xl bg-indigo-50 hover:bg-indigo-100 transition-colors flex items-center justify-center gap-3">
<svg class="w-6 h-6 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/>
</svg>
<span class="text-indigo-700 font-medium">Sélectionner depuis la galerie</span>
</button>
<input type="file" id="file-upload" class="file-input" accept="image/*,text/*"
capture="environment" multiple>
</div>
<!-- Upload Zone -->
<div class="upload-zone border-2 border-dashed border-gray-300 rounded-2xl p-8 text-center cursor-pointer transition-all duration-300 relative overflow-hidden">
<div class="space-y-4">
<div class="w-20 h-20 mx-auto rounded-full bg-indigo-50 flex items-center justify-center">
<svg class="w-10 h-10 text-indigo-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"/>
</svg>
</div>
<div class="text-sm text-gray-600">
<p>Déposez votre fichier ici</p>
<p class="text-xs text-gray-500 mt-2">ou</p>
<p class="text-indigo-600 font-medium mt-2">Cliquez pour sélectionner</p>
</div>
</div>
</div>
<!-- Preview -->
<div id="preview" class="mt-12 hidden slide-up">
<h3 class="text-xl font-medium text-gray-900 mb-6">Aperçu du document</h3>
<div class="preview-container border rounded-xl p-6 bg-gray-50">
<img id="image-preview" class="max-w-full h-auto hidden rounded-lg shadow-lg" alt="Aperçu">
<pre id="text-preview" class="text-sm text-gray-700 whitespace-pre-wrap hidden bg-white p-4 rounded-lg shadow-inner"></pre>
</div>
</div>
<!-- Submit Button -->
<div class="mt-8">
<button id="submit-button"
class="button-submit w-full py-4 px-8 rounded-xl text-white font-medium text-lg disabled:opacity-50 disabled:cursor-not-allowed hidden"
onclick="submitAnalysis()">
Analyser le document
</button>
</div>
<!-- Analysis Results -->
<div id="results" class="mt-12 hidden slide-up">
<h3 class="text-xl font-medium text-gray-900 mb-6">Analyse détaillée</h3>
<div class="bg-white rounded-xl p-6 shadow-inner">
<div id="analysis-content" class="prose prose-indigo"></div>
</div>
</div>
</div>
</div>
<!-- Loading Spinner -->
<div id="loading" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden backdrop-blur-sm z-50">
<div class="bg-white p-8 rounded-2xl shadow-2xl">
<div class="animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-indigo-500 mx-auto"></div>
<p class="text-gray-700 mt-4">Analyse en cours...</p>
</div>
</div>
<script>
let selectedFile = null;
function selectDocType(type) {
document.querySelectorAll('.option-card').forEach(card => {
card.classList.remove('border-indigo-500');
card.classList.add('border-gray-200');
});
const selectedCard = document.querySelector(`[onclick="selectDocType('${type}')"]`);
selectedCard.classList.remove('border-gray-200');
selectedCard.classList.add('border-indigo-500');
const radio = selectedCard.querySelector('input[type="radio"]');
radio.checked = true;
}
function openFileSelection() {
document.getElementById('file-upload').click();
}
function handleFile(file) {
selectedFile = file;
const submitButton = document.getElementById('submit-button');
submitButton.classList.remove('hidden');
// Preview logic
const preview = document.getElementById('preview');
const imagePreview = document.getElementById('image-preview');
const textPreview = document.getElementById('text-preview');
preview.classList.remove('hidden');
preview.classList.add('fade-in');
const docType = document.querySelector('input[name="docType"]:checked').value;
if (docType === 'iconographic' && file.type.startsWith('image/')) {
imagePreview.classList.remove('hidden');
textPreview.classList.add('hidden');
const reader = new FileReader();
reader.onload = (e) => {
imagePreview.src = e.target.result;
imagePreview.classList.add('fade-in');
};
reader.readAsDataURL(file);
} else {
imagePreview.classList.add('hidden');
textPreview.classList.remove('hidden');
const reader = new FileReader();
reader.onload = (e) => {
textPreview.textContent = e.target.result;
textPreview.classList.add('fade-in');
};
reader.readAsText(file);
}
}
function submitAnalysis() {
if (!selectedFile) return;
const formData = new FormData();
formData.append('file', selectedFile);
formData.append('docType', document.querySelector('input[name="docType"]:checked').value);
const loading = document.getElementById('loading');
const results = document.getElementById('results');
const analysisContent = document.getElementById('analysis-content');
loading.classList.remove('hidden');
loading.classList.add('fade-in');
fetch('/upload', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
loading.classList.add('hidden');
results.classList.remove('hidden');
results.classList.add('slide-up');
analysisContent.innerHTML = marked.parse(data.analysis);
Prism.highlightAll();
})
.catch(error => {
loading.classList.add('hidden');
alert('Une erreur est survenue lors de l\'analyse. Veuillez réessayer.');
console.error('Error:', error);
});
}
// Event Listeners
document.addEventListener('DOMContentLoaded', function() {
const uploadZone = document.querySelector('.upload-zone');
const fileInput = document.getElementById('file-upload');
uploadZone.addEventListener('click', () => fileInput.click());
uploadZone.addEventListener('dragover', (e) => {
e.preventDefault();
uploadZone.classList.add('border-indigo-500', 'bg-indigo-50');
});
uploadZone.addEventListener('dragleave', () => {
uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
});
uploadZone.addEventListener('drop', (e) => {
e.preventDefault();
uploadZone.classList.remove('border-indigo-500', 'bg-indigo-50');
const files = e.dataTransfer.files;
if (files.length) handleFile(files[0]);
});
fileInput.addEventListener('change', (e) => {
if (e.target.files.length) handleFile(e.target.files[0]);
});
});
</script>
</body>
</html>