Spaces:
Running
Running
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Convertisseur EUR/THB</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #2563eb 0%, #7c3aed 50%, #db2777 100%); | |
| } | |
| .currency-card { | |
| backdrop-filter: blur(10px); | |
| background: rgba(255, 255, 255, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .history-item { | |
| transition: all 0.3s ease; | |
| } | |
| .history-item:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .flag-icon { | |
| width: 24px; | |
| height: 24px; | |
| border-radius: 50%; | |
| object-fit: cover; | |
| box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | |
| } | |
| #history-list::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| #history-list::-webkit-scrollbar-track { | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 10px; | |
| } | |
| #history-list::-webkit-scrollbar-thumb { | |
| background: rgba(255, 255, 255, 0.3); | |
| border-radius: 10px; | |
| } | |
| .refresh-animation { | |
| animation: pulse 1.5s infinite; | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .countdown-bar { | |
| height: 4px; | |
| background: rgba(255, 255, 255, 0.3); | |
| border-radius: 2px; | |
| overflow: hidden; | |
| } | |
| .countdown-progress { | |
| height: 100%; | |
| background: white; | |
| width: 100%; | |
| transition: width 0.5s linear; | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen gradient-bg text-white"> | |
| <div class="container mx-auto px-4 py-8"> | |
| <header class="text-center mb-10"> | |
| <h1 class="text-4xl font-bold mb-2">Convertisseur EUR ↔ THB</h1> | |
| <p class="text-lg opacity-80">Convertissez facilement entre euros et bahts thaïlandais</p> | |
| </header> | |
| <div class="max-w-3xl mx-auto"> | |
| <!-- Carte de conversion --> | |
| <div class="currency-card rounded-xl p-6 mb-8 shadow-lg"> | |
| <div class="flex flex-col md:flex-row gap-6"> | |
| <!-- Montant à convertir --> | |
| <div class="flex-1"> | |
| <label for="amount" class="block text-sm font-medium mb-2">Montant</label> | |
| <div class="relative"> | |
| <input type="number" id="amount" | |
| class="w-full px-4 py-3 rounded-lg bg-white/10 border border-white/20 focus:outline-none focus:ring-2 focus:ring-blue-400" | |
| placeholder="0.00" step="0.01" min="0"> | |
| <div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"> | |
| <span class="text-gray-300" id="from-currency-symbol">€</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Sélecteur de devise --> | |
| <div class="flex-1"> | |
| <label for="from-currency" class="block text-sm font-medium mb-2">De</label> | |
| <div class="relative"> | |
| <select id="from-currency" | |
| class="w-full px-4 py-3 rounded-lg bg-white/10 border border-white/20 focus:outline-none focus:ring-2 focus:ring-blue-400 appearance-none"> | |
| <option value="EUR">EUR - Euro</option> | |
| <option value="THB">THB - Baht thaïlandais</option> | |
| </select> | |
| <div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"> | |
| <i class="fas fa-chevron-down text-gray-300"></i> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Bouton d'inversion --> | |
| <div class="flex items-center justify-center"> | |
| <button id="swap-currencies" | |
| class="p-3 rounded-full bg-white/20 hover:bg-white/30 transition-colors duration-200"> | |
| <i class="fas fa-exchange-alt"></i> | |
| </button> | |
| </div> | |
| <!-- Sélecteur de devise cible --> | |
| <div class="flex-1"> | |
| <label for="to-currency" class="block text-sm font-medium mb-2">Vers</label> | |
| <div class="relative"> | |
| <select id="to-currency" | |
| class="w-full px-4 py-3 rounded-lg bg-white/10 border border-white/20 focus:outline-none focus:ring-2 focus:ring-blue-400 appearance-none"> | |
| <option value="THB">THB - Baht thaïlandais</option> | |
| <option value="EUR">EUR - Euro</option> | |
| </select> | |
| <div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none"> | |
| <i class="fas fa-chevron-down text-gray-300"></i> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Résultat de la conversion --> | |
| <div class="mt-8 text-center"> | |
| <div class="text-sm mb-2">Montant converti</div> | |
| <div id="conversion-result" class="text-4xl font-bold">0.00</div> | |
| <div id="conversion-rate" class="text-sm opacity-80 mt-2 flex items-center justify-center"> | |
| <span id="rate-value">1 EUR = 38.50 THB</span> | |
| <button id="manual-refresh" class="ml-2 text-white/60 hover:text-white transition-colors"> | |
| <i class="fas fa-sync-alt"></i> | |
| </button> | |
| </div> | |
| <div class="countdown-bar mt-2"> | |
| <div id="countdown-progress" class="countdown-progress"></div> | |
| </div> | |
| </div> | |
| <!-- Bouton de conversion --> | |
| <div class="mt-8 text-center"> | |
| <button id="convert-btn" | |
| class="px-6 py-3 bg-blue-500 hover:bg-blue-600 rounded-lg font-medium transition-colors duration-200"> | |
| Convertir | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Taux de change --> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8"> | |
| <div class="currency-card rounded-xl p-6"> | |
| <div class="flex items-center mb-4"> | |
| <img src="https://flagcdn.com/w40/eu.png" class="flag-icon mr-2"> | |
| <h3 class="text-lg font-medium">1 Euro (EUR)</h3> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <span class="text-2xl font-bold" id="eur-to-thb">38.50</span> | |
| <span class="text-sm opacity-80">Baht thaïlandais</span> | |
| </div> | |
| </div> | |
| <div class="currency-card rounded-xl p-6"> | |
| <div class="flex items-center mb-4"> | |
| <img src="https://flagcdn.com/w40/th.png" class="flag-icon mr-2"> | |
| <h3 class="text-lg font-medium">1 Baht thaïlandais (THB)</h3> | |
| </div> | |
| <div class="flex items-center justify-between"> | |
| <span class="text-2xl font-bold" id="thb-to-eur">0.026</span> | |
| <span class="text-sm opacity-80">Euros</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Historique des conversions --> | |
| <div class="currency-card rounded-xl p-6"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-lg font-medium flex items-center"> | |
| <i class="fas fa-history mr-2"></i> Historique des conversions | |
| </h3> | |
| <button id="clear-history" class="text-sm bg-red-500/20 hover:bg-red-500/30 px-3 py-1 rounded-lg flex items-center transition-colors duration-200"> | |
| <i class="fas fa-trash-alt mr-1"></i> Effacer | |
| </button> | |
| </div> | |
| <div id="history-list" class="space-y-3 max-h-64 overflow-y-auto pr-2"> | |
| <!-- Les éléments d'historique seront ajoutés ici dynamiquement --> | |
| <div class="text-center py-4 text-gray-300" id="empty-history"> | |
| Aucune conversion enregistrée | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <footer class="mt-12 text-center text-sm opacity-70"> | |
| <p>Taux de change actualisés toutes les 15 minutes. Dernière mise à jour: <span id="last-updated">chargement...</span></p> | |
| <p class="mt-2">© 2025 Convertisseur EUR/THB - Tous droits réservés Patrick Pansaerts</p> | |
| </footer> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Taux de change (simulé - en réalité on ferait une requête API) | |
| let exchangeRate = 38.50; // 1 EUR = 38.50 THB | |
| let lastUpdated = new Date(); | |
| let nextRefreshTime = new Date(); | |
| let refreshInterval = 15 * 60 * 1000; // 15 minutes en millisecondes | |
| let countdownInterval; | |
| // Éléments du DOM | |
| const amountInput = document.getElementById('amount'); | |
| const fromCurrency = document.getElementById('from-currency'); | |
| const toCurrency = document.getElementById('to-currency'); | |
| const swapBtn = document.getElementById('swap-currencies'); | |
| const convertBtn = document.getElementById('convert-btn'); | |
| const conversionResult = document.getElementById('conversion-result'); | |
| const conversionRate = document.getElementById('conversion-rate'); | |
| const rateValue = document.getElementById('rate-value'); | |
| const eurToThb = document.getElementById('eur-to-thb'); | |
| const thbToEur = document.getElementById('thb-to-eur'); | |
| const lastUpdatedSpan = document.getElementById('last-updated'); | |
| const historyList = document.getElementById('history-list'); | |
| const emptyHistory = document.getElementById('empty-history'); | |
| const fromCurrencySymbol = document.getElementById('from-currency-symbol'); | |
| const clearHistoryBtn = document.getElementById('clear-history'); | |
| const manualRefreshBtn = document.getElementById('manual-refresh'); | |
| const countdownProgress = document.getElementById('countdown-progress'); | |
| // Mettre à jour les taux affichés | |
| function updateExchangeRates() { | |
| // Animation de rafraîchissement | |
| rateValue.classList.add('refresh-animation'); | |
| setTimeout(() => { | |
| rateValue.classList.remove('refresh-animation'); | |
| }, 1500); | |
| eurToThb.textContent = exchangeRate.toFixed(2); | |
| thbToEur.textContent = (1 / exchangeRate).toFixed(3); | |
| rateValue.textContent = `1 EUR = ${exchangeRate.toFixed(2)} THB`; | |
| // Formater la date de mise à jour | |
| const options = { | |
| year: 'numeric', | |
| month: 'long', | |
| day: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit', | |
| second: '2-digit' | |
| }; | |
| lastUpdatedSpan.textContent = lastUpdated.toLocaleDateString('fr-FR', options); | |
| // Mettre à jour le prochain temps de rafraîchissement | |
| nextRefreshTime = new Date(lastUpdated.getTime() + refreshInterval); | |
| startCountdown(); | |
| } | |
| // Simuler la récupération des taux de change | |
| function fetchExchangeRates() { | |
| // Simulation: taux aléatoire autour de 38.50 pour l'exemple | |
| exchangeRate = 38.50 + (Math.random() * 0.5 - 0.25); | |
| lastUpdated = new Date(); | |
| updateExchangeRates(); | |
| // En production, on utiliserait une API réelle: | |
| // fetch('https://api.exchangerate-api.com/v4/latest/EUR') | |
| // .then(response => response.json()) | |
| // .then(data => { | |
| // exchangeRate = data.rates.THB; | |
| // lastUpdated = new Date(data.time_last_updated * 1000); | |
| // updateExchangeRates(); | |
| // }); | |
| } | |
| // Démarrer le compte à rebours | |
| function startCountdown() { | |
| clearInterval(countdownInterval); | |
| countdownInterval = setInterval(() => { | |
| const now = new Date(); | |
| const timeLeft = nextRefreshTime - now; | |
| if (timeLeft <= 0) { | |
| fetchExchangeRates(); | |
| return; | |
| } | |
| const progress = 100 - (timeLeft / refreshInterval * 100); | |
| countdownProgress.style.width = `${progress}%`; | |
| }, 1000); | |
| } | |
| // Effectuer la conversion | |
| function performConversion() { | |
| const amount = parseFloat(amountInput.value); | |
| if (isNaN(amount) || amount <= 0) { | |
| alert('Veuillez entrer un montant valide'); | |
| return; | |
| } | |
| const from = fromCurrency.value; | |
| const to = toCurrency.value; | |
| let result; | |
| if (from === 'EUR' && to === 'THB') { | |
| result = amount * exchangeRate; | |
| conversionResult.textContent = result.toFixed(2); | |
| } else if (from === 'THB' && to === 'EUR') { | |
| result = amount / exchangeRate; | |
| conversionResult.textContent = result.toFixed(2); | |
| } else { | |
| // Même devise | |
| result = amount; | |
| conversionResult.textContent = amount.toFixed(2); | |
| } | |
| // Ajouter à l'historique | |
| addToHistory(amount, from, result, to); | |
| } | |
| // Ajouter une conversion à l'historique | |
| function addToHistory(amount, from, result, to) { | |
| if (emptyHistory) { | |
| emptyHistory.style.display = 'none'; | |
| } | |
| const historyItem = document.createElement('div'); | |
| historyItem.className = 'history-item bg-white/5 p-4 rounded-lg'; | |
| const fromFlag = from === 'EUR' ? 'eu' : 'th'; | |
| const toFlag = to === 'EUR' ? 'eu' : 'th'; | |
| historyItem.innerHTML = ` | |
| <div class="flex justify-between items-center"> | |
| <div class="flex items-center"> | |
| <img src="https://flagcdn.com/w20/${fromFlag}.png" class="flag-icon mr-2"> | |
| <span class="font-medium">${amount.toFixed(2)} ${from}</span> | |
| </div> | |
| <i class="fas fa-arrow-right mx-2 text-gray-400"></i> | |
| <div class="flex items-center"> | |
| <img src="https://flagcdn.com/w20/${toFlag}.png" class="flag-icon mr-2"> | |
| <span class="font-medium">${result.toFixed(2)} ${to}</span> | |
| </div> | |
| </div> | |
| <div class="text-xs text-gray-400 mt-1"> | |
| ${new Date().toLocaleString('fr-FR')} | |
| </div> | |
| `; | |
| historyList.insertBefore(historyItem, historyList.firstChild); | |
| } | |
| // Effacer l'historique | |
| function clearHistory() { | |
| while (historyList.firstChild) { | |
| historyList.removeChild(historyList.firstChild); | |
| } | |
| emptyHistory.style.display = 'block'; | |
| } | |
| // Inverser les devises | |
| function swapCurrencies() { | |
| const temp = fromCurrency.value; | |
| fromCurrency.value = toCurrency.value; | |
| toCurrency.value = temp; | |
| // Mettre à jour le symbole | |
| updateCurrencySymbol(); | |
| } | |
| // Mettre à jour le symbole de la devise | |
| function updateCurrencySymbol() { | |
| fromCurrencySymbol.textContent = fromCurrency.value === 'EUR' ? '€' : '฿'; | |
| } | |
| // Événements | |
| swapBtn.addEventListener('click', swapCurrencies); | |
| convertBtn.addEventListener('click', performConversion); | |
| fromCurrency.addEventListener('change', updateCurrencySymbol); | |
| clearHistoryBtn.addEventListener('click', clearHistory); | |
| manualRefreshBtn.addEventListener('click', fetchExchangeRates); | |
| // Permettre la conversion avec la touche Entrée | |
| amountInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') { | |
| performConversion(); | |
| } | |
| }); | |
| // Initialisation | |
| fetchExchangeRates(); | |
| updateCurrencySymbol(); | |
| // Configurer l'actualisation automatique toutes les 15 minutes | |
| setInterval(fetchExchangeRates, refreshInterval); | |
| }); | |
| </script> | |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=cppbel/convertisseur-eur-thb" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |