| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- <!-- URL Shortener Form Component -->
- <div class="max-w-2xl mx-auto">
- <div class="bg-white rounded-2xl shadow-sm border border-gray-100 p-8 relative">
- <form id="shortenForm" class="space-y-6">
- <div class="relative">
- <input
- type="url"
- id="url"
- name="url"
- placeholder="Pega tu enlace aquí..."
- class="w-full px-6 py-4 text-lg border border-gray-200 rounded-xl focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-200 bg-gray-50 focus:bg-white"
- required
- >
- </div>
-
- <div class="relative">
- <label for="duration" class="block text-sm font-medium text-gray-700 mb-2">
- <i class="fas fa-clock mr-1"></i>Duración del enlace
- </label>
- <select
- id="duration"
- name="duration"
- class="w-full px-4 py-3 border border-gray-200 rounded-xl focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-200 bg-gray-50 focus:bg-white"
- >
- <option value="never">Nunca expira</option>
- <option value="1hour">1 hora</option>
- <option value="1day">1 día</option>
- <option value="1week">1 semana</option>
- <option value="1month">1 mes</option>
- <option value="1year">1 año</option>
- </select>
- </div>
-
- <button
- type="submit"
- class="w-full bg-primary hover:bg-secondary text-white font-medium py-4 px-6 rounded-xl transition-all duration-200 text-lg"
- >
- Acortar enlace
- </button>
- </form>
- <!-- Success Animation (overlays the form) -->
- <div id="successAnimation" class="hidden absolute inset-0 bg-white bg-opacity-95 flex items-center justify-center rounded-2xl z-10">
- <div class="text-center">
- <div id="checkmarkContainer" class="w-24 h-24 mx-auto mb-4 relative">
- <div class="w-24 h-24 bg-green-500 rounded-full flex items-center justify-center transform scale-0 transition-transform duration-600 ease-out" id="checkmarkCircle">
- <i class="fas fa-check text-white text-4xl opacity-0 transition-opacity duration-400" id="checkmarkIcon"></i>
- </div>
- </div>
- <h3 class="text-2xl font-bold text-green-600 opacity-0 transition-opacity duration-500" id="successText">¡Enlace acortado!</h3>
- </div>
- </div>
- <!-- Result Section -->
- <div id="result" class="hidden p-6 bg-green-50 border border-green-200 rounded-xl transform translate-y-4 opacity-0 transition-all duration-500 ease-out">
- <div class="text-center mb-4">
- <i class="fas fa-check-circle text-green-600 text-2xl mb-2"></i>
- <h3 class="text-lg font-medium text-green-800">¡Listo!</h3>
- <p class="text-green-700">Tu enlace ha sido acortado exitosamente</p>
- </div>
- <div class="space-y-4">
- <div>
- <label class="block text-sm font-medium text-green-700 mb-2">Tu enlace acortado:</label>
- <div class="flex items-center space-x-3">
- <input
- type="text"
- id="shortUrl"
- readonly
- class="flex-1 font-mono bg-white p-3 rounded-lg border focus:outline-none text-center"
- >
- <button
- onclick="copyToClipboard(document.getElementById('shortUrl').value)"
- class="bg-primary hover:bg-secondary text-white px-4 py-3 rounded-lg transition-colors duration-200 flex-shrink-0"
- title="Copiar enlace"
- >
- <i class="fas fa-copy"></i>
- </button>
- </div>
- </div>
- <div class="text-center pt-4">
- <button
- onclick="resetForm()"
- class="bg-gray-600 hover:bg-gray-700 text-white font-medium py-3 px-6 rounded-xl transition-all duration-200"
- >
- <i class="fas fa-plus mr-2"></i>Acortar otro enlace
- </button>
- </div>
- </div>
- </div>
- </div>
- </div>
- <script>
- // Form submission handler
- document.getElementById('shortenForm').addEventListener('submit', async function(e) {
- e.preventDefault();
-
- const url = document.getElementById('url').value;
- const duration = document.getElementById('duration').value;
- const resultDiv = document.getElementById('result');
- const shortUrlInput = document.getElementById('shortUrl');
-
- try {
- const response = await fetch('/shorten', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ url: url, duration: duration })
- });
-
- const data = await response.json();
-
- if (data.success) {
- shortUrlInput.value = data.short_url;
-
- // Show success animation first
- showSuccessAnimation(() => {
- // Hide form and show result after animation
- document.getElementById('shortenForm').style.display = 'none';
- resultDiv.classList.remove('hidden');
-
- // Animate result appearance
- setTimeout(() => {
- resultDiv.style.transform = 'translateY(0)';
- resultDiv.style.opacity = '1';
- }, 50);
-
- showToast('¡Enlace acortado exitosamente!', 'success');
- });
- } else {
- showToast(data.error || 'Error al acortar el enlace', 'error');
- }
- } catch (error) {
- showToast('Error de conexión', 'error');
- }
- });
- // Function to show success animation
- function showSuccessAnimation(callback) {
- const successAnimation = document.getElementById('successAnimation');
- const checkmarkCircle = document.getElementById('checkmarkCircle');
- const checkmarkIcon = document.getElementById('checkmarkIcon');
- const successText = document.getElementById('successText');
-
- // Show animation container
- successAnimation.classList.remove('hidden');
-
- // Animate checkmark circle
- setTimeout(() => {
- checkmarkCircle.style.transform = 'scale(1)';
- }, 100);
-
- // Show checkmark icon
- setTimeout(() => {
- checkmarkIcon.style.opacity = '1';
- }, 400);
-
- // Show success text
- setTimeout(() => {
- successText.style.opacity = '1';
- }, 700);
-
- // Hide animation and show result
- setTimeout(() => {
- successAnimation.classList.add('hidden');
- // Reset animation states
- checkmarkCircle.style.transform = 'scale(0)';
- checkmarkIcon.style.opacity = '0';
- successText.style.opacity = '0';
-
- // Execute callback to show result
- if (callback) callback();
- }, 2000);
- }
- // Function to reset form
- function resetForm() {
- const resultDiv = document.getElementById('result');
-
- // Animate result disappearance
- resultDiv.style.transform = 'translateY(4px)';
- resultDiv.style.opacity = '0';
-
- setTimeout(() => {
- document.getElementById('shortenForm').style.display = 'block';
- resultDiv.classList.add('hidden');
- document.getElementById('url').value = '';
- document.getElementById('shortUrl').value = '';
-
- // Reset result animation state
- resultDiv.style.transform = 'translateY(4px)';
- resultDiv.style.opacity = '0';
- }, 300);
- }
- </script>
|