Mariam-cards / templates /index.html
Docfile's picture
Create templates/index.html
1d14a8b verified
raw
history blame
10.4 kB
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Flashcards Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.6.2/axios.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Space Grotesk', sans-serif;
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
}
.glass-morph {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.card-hover {
transition: all 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
}
.gradient-text {
background: linear-gradient(45deg, #60a5fa, #a855f7);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.custom-loader {
width: 50px;
height: 50px;
border: 3px solid #fff;
border-radius: 50%;
display: inline-block;
position: relative;
box-sizing: border-box;
animation: rotation 1s linear infinite;
}
.custom-loader::after {
content: '';
box-sizing: border-box;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid transparent;
border-bottom-color: #60a5fa;
}
@keyframes rotation {
0% { transform: rotate(0deg) }
100% { transform: rotate(360deg) }
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
</head>
<body class="min-h-screen text-gray-100">
<div id="app" class="container mx-auto px-4 py-12">
<!-- Hero Section -->
<div class="text-center mb-16 animate__animated animate__fadeIn">
<h1 class="text-5xl font-bold mb-4 gradient-text">AI Flashcards Generator</h1>
<p class="text-xl text-gray-400 mb-8">Transformez vos sujets en cartes d'apprentissage intelligentes</p>
</div>
<!-- Main Content -->
<div class="max-w-4xl mx-auto">
<!-- Input Section -->
<div class="glass-morph rounded-2xl p-8 mb-12 card-hover">
<div class="mb-6">
<label for="topic" class="block text-lg font-medium mb-3 text-gray-300">Quel sujet souhaitez-vous explorer ?</label>
<div class="relative">
<input
type="text"
id="topic"
v-model="topic"
class="w-full px-6 py-4 bg-gray-800/50 rounded-xl border border-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent text-lg transition-all duration-300"
placeholder="Ex: Intelligence Artificielle, Quantum Computing..."
:disabled="isLoading"
>
</div>
</div>
<button
@click="generateFlashcards"
:disabled="isLoading"
class="w-full bg-gradient-to-r from-blue-500 to-purple-600 text-white py-4 px-8 rounded-xl font-medium text-lg hover:opacity-90 transition-all duration-300 flex items-center justify-center space-x-3"
>
<span v-if="!isLoading">Générer les Flashcards</span>
<span v-else class="custom-loader"></span>
</button>
</div>
<!-- Error Message -->
<transition name="fade">
<div v-if="error" class="mb-8 animate__animated animate__shakeX">
<div class="bg-red-500/20 border border-red-500/50 text-red-300 px-6 py-4 rounded-xl">
[[error]]
</div>
</div>
</transition>
<!-- Results Section -->
<transition name="fade">
<div v-if="flashcards.length > 0" class="glass-morph rounded-2xl overflow-hidden">
<!-- Tabs -->
<div class="border-b border-gray-700/50">
<div class="flex">
<button
v-for="tab in ['study', 'json']"
:key="tab"
@click="activeTab = tab"
:class="[
'px-8 py-4 font-medium text-lg transition-all duration-300',
activeTab === tab
? 'gradient-text border-b-2 border-blue-500'
: 'text-gray-400 hover:text-gray-300'
]"
>
[[tab === 'study' ? 'Mode Étude' : 'Mode JSON']]
</button>
</div>
</div>
<!-- Tab Content -->
<div class="p-6">
<!-- Study Mode -->
<div v-if="activeTab === 'study'" class="space-y-6">
<div
v-for="(card, index) in flashcards"
:key="index"
class="glass-morph rounded-xl p-6 card-hover cursor-pointer transition-all duration-300"
@click="card.showAnswer = !card.showAnswer"
>
<div class="flex items-start space-x-4">
<div class="w-12 h-12 flex items-center justify-center rounded-full bg-blue-500/20 text-blue-400 font-bold">
[[index + 1]]
</div>
<div class="flex-1">
<h3 class="text-xl font-medium mb-4">[[card.question]]</h3>
<transition name="fade">
<div v-if="card.showAnswer" class="mt-4 pt-4 border-t border-gray-700/50">
<p class="text-gray-300">[[card.answer]]</p>
</div>
</transition>
</div>
</div>
</div>
</div>
<!-- JSON Mode -->
<div v-if="activeTab === 'json'" class="bg-gray-800/50 rounded-xl p-6 overflow-x-auto">
<pre class="text-gray-300">[[JSON.stringify(flashcards, null, 2)]]</pre>
</div>
</div>
</div>
</transition>
</div>
</div>
<script>
const { createApp } = Vue
createApp({
delimiters: ['[[', ']]'],
data() {
return {
topic: '',
flashcards: [],
activeTab: 'study',
isLoading: false,
error: null
}
},
methods: {
async generateFlashcards() {
if (!this.topic) {
this.error = 'Veuillez entrer un sujet.'
return
}
this.isLoading = true
this.error = null
this.flashcards = []
try {
const response = await axios.post('/generate', {
topic: this.topic
})
if (response.data.success) {
const cards = response.data.flashcards.map(card => ({
...card,
showAnswer: false
}))
// Animation des cartes à leur apparition
setTimeout(() => {
this.flashcards = cards
this.$nextTick(() => {
gsap.from('.card-hover', {
y: 30,
opacity: 0,
duration: 0.5,
stagger: 0.1
})
})
}, 300)
}
} catch (error) {
this.error = error.response?.data?.error || 'Une erreur est survenue lors de la génération.'
} finally {
this.isLoading = false
}
}
},
mounted() {
// Animation du titre à l'entrée
gsap.from('.gradient-text', {
y: -50,
opacity: 0,
duration: 1,
ease: 'power3.out'
})
}
}).mount('#app')
</script>
</body>
</html>